def dump_macinfo(macaddr): macaddr = macaddr.replace('-', ':') info = _macmap.get(macaddr, None) if info is None: raise exc.NotFoundException('{0} not found in mac table of ' 'any known switches'.format(macaddr)) return _dump_locations(info, macaddr, _nodesbymac.get(macaddr, (None, ))[0])
def enumerate_nodegroup_collection(collectionpath, configmanager): nodegroup = collectionpath[1] if not configmanager.is_nodegroup(nodegroup): raise exc.NotFoundException( 'Invalid nodegroup: {0} not found'.format(nodegroup)) del collectionpath[0:2] collection = nested_lookup(nodegroupresources, collectionpath) return iterate_resources(collection)
def _get_mac_from_query(pathcomponents): _, queryparms, _, _ = _parameterize_path(pathcomponents[1:]) if 'by-mac' not in queryparms: raise exc.InvalidArgumentException('Must target using "by-mac"') mac = queryparms['by-mac'].replace('-', ':') if mac not in known_info: raise exc.NotFoundException('{0} not found'.format(mac)) return mac
def enumerate_node_collection(collectionpath, configmanager): if collectionpath == ['nodes']: # it is just '/node/', need to list nodes allnodes = list(configmanager.list_nodes()) try: allnodes.sort(key=noderange.humanify_nodename) except TypeError: allnodes.sort() return iterate_collections(allnodes) nodeorrange = collectionpath[1] if collectionpath[0] == 'nodes' and not configmanager.is_node(nodeorrange): raise exc.NotFoundException("Invalid element requested") collection = nested_lookup(noderesources, collectionpath[2:]) if len(collectionpath) == 2 and collectionpath[0] == 'noderange': collection['nodes'] = {} if not isinstance(collection, dict): raise exc.NotFoundException("Invalid element requested") return iterate_resources(collection)
def nested_lookup(nestdict, key): try: currloc = nestdict for currk in key: currloc = seek_element(currloc, currk) return currloc except TypeError: raise exc.NotFoundException("Invalid element requested")
def nested_lookup(nestdict, key): try: currloc = nestdict for i in range(len(key)): currk = key[i] currloc = seek_element(currloc, currk, len(key) - i) return currloc except TypeError: raise exc.NotFoundException("Invalid element requested")
def _handle_neighbor_query(pathcomponents, configmanager): choices, parms, listrequested, childcoll = _parameterize_path( pathcomponents) if not childcoll: # this means it's a single entry with by-peerid # guaranteed if (parms['by-peerid'] not in _neighbypeerid and _neighbypeerid.get('!!vintage', 0) < util.monotonic_time() - 60): list(update_neighbors(configmanager)) if parms['by-peerid'] not in _neighbypeerid: raise exc.NotFoundException('No matching peer known') return _dump_neighbordatum(_neighbypeerid[parms['by-peerid']]) if not listrequested: # the query is for currently valid choices return [msg.ChildCollection(x + '/') for x in sorted(list(choices))] if listrequested not in multi_selectors | single_selectors: raise exc.NotFoundException('{0} is not found'.format(listrequested)) if 'by-switch' in parms: update_switch_data(parms['by-switch'], configmanager) else: list(update_neighbors(configmanager)) return list_info(parms, listrequested)
def handle_deployment(configmanager, inputdata, pathcomponents, operation): if len(pathcomponents) == 1: yield msg.ChildCollection('distributions/') yield msg.ChildCollection('profiles/') yield msg.ChildCollection('importing/') return if pathcomponents[1] == 'distributions': if len(pathcomponents) == 2 and operation == 'retrieve': for dist in osimage.list_distros(): yield msg.ChildCollection(dist + '/') return if len(pathcomponents) == 3: distname = pathcomponents[-1] if 'operation' == 'update': if inputdata.get('rescan', False): osimage.rescan_dist(distname) if pathcomponents[1] == 'profiles': if len(pathcomponents) == 2 and operation == 'retrieve': for prof in osimage.list_profiles(): yield msg.ChildCollection(prof + '/') return if len(pathcomponents) == 3: profname = pathcomponents[-1] if operation == 'update' and 'updateboot' in inputdata: osimage.update_boot(profname) yield msg.KeyValueData({'updated': profname}) return if pathcomponents[1] == 'importing': if len(pathcomponents) == 2 or not pathcomponents[-1]: if operation == 'retrieve': for imp in osimage.list_importing(): yield imp return elif operation == 'create': importer = osimage.MediaImporter(inputdata['filename'], configmanager) yield msg.KeyValueData({ 'target': importer.targpath, 'name': importer.importkey }) return elif len(pathcomponents) == 3: if operation == 'retrieve': for res in osimage.get_importing_status(pathcomponents[-1]): yield res return elif operation == 'delete': for res in osimage.remove_importing(pathcomponents[-1]): yield res return raise exc.NotFoundException('Unrecognized request')
def remove_updates(nodes, tenant, element): if len(element) < 5: raise exc.InvalidArgumentException() upid = element[-1] for node in nodes: try: upd = updatesbytarget[(node, tenant)][upid] except KeyError: raise exc.NotFoundException('No active update matches request') upd.cancel() del updatesbytarget[(node, tenant)][upid] yield msg.DeletedResource( 'nodes/{0}/inventory/firmware/updates/active/{1}'.format( node, upid))
def list_updates(nodes, tenant, element): showmode = False if len(element) > 4: showmode = True upid = element[-1] for node in nodes: if showmode: try: updater = updatesbytarget[(node, tenant)][upid] except KeyError: raise exc.NotFoundException('No matching update process found') yield msg.KeyValueData(updater.progress, name=node) else: for updateid in updatesbytarget.get((node, tenant), {}): yield msg.ChildCollection(updateid)
def handle_read_api_request(pathcomponents): # TODO(jjohnson2): This should be more generalized... # odd indexes into components are 'by-'*, even indexes # starting at 2 are parameters to previous index subcats, queryparms, indexof, coll = _parameterize_path(pathcomponents[1:]) if len(pathcomponents) == 1: dirlist = [msg.ChildCollection(x + '/') for x in sorted(list(subcats))] dirlist.append(msg.ChildCollection('rescan')) return dirlist if not coll: return show_info(queryparms['by-mac']) if not indexof: return [msg.ChildCollection(x + '/') for x in sorted(list(subcats))] if indexof not in list_info: raise exc.NotFoundException('{0} is not found'.format(indexof)) return list_info[indexof](queryparms)
def remove_updates(nodes, tenant, element, type='firmware'): if len(element) < 5 and element[:2] != ['media', 'uploads']: raise exc.InvalidArgumentException() upid = element[-1] if type == 'firmware': myparty = updatesbytarget else: myparty = uploadsbytarget for node in nodes: try: upd = myparty[(node, tenant)][upid] except KeyError: raise exc.NotFoundException('No active update matches request') upd.cancel() del myparty[(node, tenant)][upid] yield msg.DeletedResource( 'nodes/{0}/inventory/firmware/updates/active/{1}'.format( node, upid))
def handle_nodegroup_request(configmanager, inputdata, pathcomponents, operation): iscollection = False routespec = None if len(pathcomponents) < 2: if operation == "create": inputdata = msg.InputAttributes(pathcomponents, inputdata) return create_group(inputdata.attribs, configmanager) allgroups = list(configmanager.get_groups()) try: allgroups.sort(key=noderange.humanify_nodename) except TypeError: allgroups.sort() return iterate_collections(allgroups) elif len(pathcomponents) == 2: iscollection = True else: try: routespec = nested_lookup(nodegroupresources, pathcomponents[2:]) if isinstance(routespec, dict): iscollection = True elif isinstance(routespec, PluginCollection): iscollection = False # it is a collection, but plugin defined except KeyError: raise exc.NotFoundException("Invalid element requested") if iscollection: if operation == "delete": return delete_nodegroup_collection(pathcomponents, configmanager) elif operation == "retrieve": return enumerate_nodegroup_collection(pathcomponents, configmanager) else: raise Exception("TODO") plugroute = routespec.routeinfo inputdata = msg.get_input_message(pathcomponents[2:], operation, inputdata) if 'handler' in plugroute: # fixed handler definition hfunc = getattr(pluginmap[plugroute['handler']], operation) return hfunc(nodes=None, element=pathcomponents, configmanager=configmanager, inputdata=inputdata) raise Exception("unknown case encountered")
def _parameterize_path(pathcomponents): listrequested = False childcoll = True if len(pathcomponents) % 2 == 1: listrequested = pathcomponents[-1] pathcomponents = pathcomponents[:-1] pathit = iter(pathcomponents) keyparams = {} validselectors = multi_selectors | single_selectors for key, val in zip(pathit, pathit): if key not in validselectors: raise exc.NotFoundException('{0} is not valid here'.format(key)) keyparams[key] = val validselectors.discard(key) if key == 'by-switch': validselectors.add('by-port') if key in single_selectors: childcoll = False validselectors = set([]) return validselectors, keyparams, listrequested, childcoll
def __init__(self, node, configmanager, username, datacallback=None, skipreplay=False, direct=True, width=80, height=24): self.registered = False self.tenant = configmanager.tenant if not configmanager.is_node(node): raise exc.NotFoundException("Invalid node") self.username = username self.node = node self.configmanager = configmanager self.direct = direct # true if client is directly connected versus # relay self.width = width self.height = height self.connect_session() self.registered = True self._evt = None self.node = node self.write = self.conshdl.write if datacallback is None: self.reaper = eventlet.spawn_after(15, self.destroy) self.databuffer = collections.deque([]) self.data_handler = self.got_data if not skipreplay: self.databuffer.extend(self.conshdl.get_recent()) else: self.data_handler = datacallback if not skipreplay: for recdata in self.conshdl.get_recent(): if recdata: datacallback(recdata) self.conshdl.attachsession(self)
def _parameterize_path(pathcomponents): listrequested = False childcoll = True if len(pathcomponents) % 2 == 1: listrequested = pathcomponents[-1] pathcomponents = pathcomponents[:-1] pathit = iter(pathcomponents) keyparams = {} validselectors = multi_selectors | node_selectors | single_selectors for key, val in zip(pathit, pathit): if key not in validselectors: raise exc.NotFoundException('{0} is not valid here'.format(key)) if key == 'by-type': keyparams[key] = servicebyname.get(val, '!!!!invalid-type') else: keyparams[key] = val validselectors.discard(key) if key in single_selectors: childcoll = False validselectors = set([]) elif key in node_selectors: validselectors = single_selectors | set([]) return validselectors, keyparams, listrequested, childcoll
def handle_api_request(configmanager, inputdata, operation, pathcomponents): if operation == 'retrieve': return handle_read_api_request(pathcomponents) elif (operation in ('update', 'create') and pathcomponents == ['discovery', 'rescan']): if inputdata != {'rescan': 'start'}: raise exc.InvalidArgumentException() rescan() return (msg.KeyValueData({'rescan': 'started'}), ) elif (operation in ('update', 'create')): if 'node' not in inputdata: raise exc.InvalidArgumentException('Missing node name in input') _, queryparms, _, _ = _parameterize_path(pathcomponents[1:]) if 'by-mac' not in queryparms: raise exc.InvalidArgumentException('Must target using "by-mac"') mac = queryparms['by-mac'].replace('-', ':') if mac not in known_info: raise exc.NotFoundException('{0} not found'.format(mac)) info = known_info[mac] handler = info['handler'].NodeHandler(info, configmanager) eval_node(configmanager, handler, info, inputdata['node'], manual=True) return [msg.AssignedResource(inputdata['node'])] raise exc.NotImplementedException('Unable to {0} to {1}'.format( operation, '/'.join(pathcomponents)))
def handle_read_api_request(pathcomponents): # TODO(jjohnson2): discovery core.py api handler design, apply it here # to make this a less tangled mess as it gets extended if len(pathcomponents) == 1: return [msg.ChildCollection('macs/')] elif len(pathcomponents) == 2: return [ msg.ChildCollection(x) for x in ( # 'by-node/', 'by-mac/', 'by-switch/', 'rescan') ] if False and pathcomponents[2] == 'by-node': # TODO: should be list of node names, and then under that 'by-mac' if len(pathcomponents) == 3: return [ msg.ChildCollection(x.replace(':', '-')) for x in sorted(list(_nodesbymac)) ] elif len(pathcomponents) == 4: macaddr = pathcomponents[-1].replace('-', ':') return dump_macinfo(macaddr) elif pathcomponents[2] == 'by-mac': if len(pathcomponents) == 3: return [ msg.ChildCollection(x.replace(':', '-')) for x in sorted(list(_macmap)) ] elif len(pathcomponents) == 4: return dump_macinfo(pathcomponents[-1]) elif pathcomponents[2] == 'by-switch': if len(pathcomponents) == 3: return [ msg.ChildCollection(x + '/') for x in sorted(list(_macsbyswitch)) ] if len(pathcomponents) == 4: return [msg.ChildCollection('by-port/')] if len(pathcomponents) == 5: switchname = pathcomponents[-2] if switchname not in _macsbyswitch: raise exc.NotFoundException( 'No known macs for switch {0}'.format(switchname)) return [ msg.ChildCollection(x.replace('/', '-') + '/') for x in sorted(list(_macsbyswitch[switchname])) ] if len(pathcomponents) == 6: return [msg.ChildCollection('by-mac/')] if len(pathcomponents) == 7: switchname = pathcomponents[-4] portname = pathcomponents[-2] try: if portname not in _macsbyswitch[switchname]: portname = portname.replace('-', '/') maclist = _macsbyswitch[switchname][portname] except KeyError: raise exc.NotFoundException('No known macs for switch {0} ' 'port {1}'.format( switchname, portname)) return [ msg.ChildCollection(x.replace(':', '-')) for x in sorted(maclist) ] if len(pathcomponents) == 8: return dump_macinfo(pathcomponents[-1]) raise exc.NotFoundException('Unrecognized path {0}'.format( '/'.join(pathcomponents)))
def retrieve_nodegroup(nodegroup, element, configmanager, inputdata): try: grpcfg = configmanager.get_nodegroup_attributes(nodegroup) except KeyError: if not configmanager.is_nodegroup(nodegroup): raise exc.NotFoundException( 'Invalid nodegroup: {0} not found'.format(nodegroup)) raise if element == 'all': theattrs = set(allattributes.node).union(set(grpcfg)) theattrs.add('nodes') for attribute in sorted(theattrs): if attribute == 'groups': continue if attribute == 'nodes': yield msg.ListAttributes( kv={'nodes': list(grpcfg.get('nodes', []))}, desc="The nodes belonging to this group") continue if attribute in grpcfg: val = grpcfg[attribute] else: val = {'value': None} if attribute.startswith('secret.'): yield msg.CryptedAttributes( kv={attribute: val}, desc=allattributes.node[attribute]['description']) elif isinstance(val, list): yield msg.ListAttributes(kv={attribute: val}, desc=allattributes.node.get( attribute, {}).get('description', '')) else: yield msg.Attributes(kv={attribute: val}, desc=allattributes.node.get( attribute, {}).get('description', '')) if element == 'current': for attribute in sorted(list(grpcfg)): currattr = grpcfg[attribute] if attribute == 'nodes': desc = 'The nodes belonging to this group' elif attribute == 'noderange': desc = 'A dynamic noderange that this group refers to in noderange expansion' else: try: desc = allattributes.node[attribute]['description'] except KeyError: desc = '' if 'value' in currattr or 'expression' in currattr: yield msg.Attributes(kv={attribute: currattr}, desc=desc) elif 'cryptvalue' in currattr: yield msg.CryptedAttributes(kv={attribute: currattr}, desc=desc) elif isinstance(currattr, set): yield msg.ListAttributes(kv={attribute: list(currattr)}, desc=desc) elif isinstance(currattr, list): yield msg.ListAttributes(kv={attribute: currattr}, desc=desc) else: print attribute print repr(currattr) raise Exception("BUGGY ATTRIBUTE FOR NODEGROUP")
def handle_node_request(configmanager, inputdata, operation, pathcomponents, autostrip=True): if log.logfull: raise exc.TargetResourceUnavailable( 'Filesystem full, free up space and restart confluent service') iscollection = False routespec = None if pathcomponents[0] == 'noderange': if len(pathcomponents) > 3 and pathcomponents[2] == 'nodes': # transform into a normal looking node request # this does mean we don't see if it is a valid # child, but that's not a goal for the noderange # facility anyway isnoderange = False pathcomponents = pathcomponents[2:] elif len(pathcomponents) == 3 and pathcomponents[2] == 'abbreviate': return abbreviate_noderange(configmanager, inputdata, operation) else: isnoderange = True else: isnoderange = False try: nodeorrange = pathcomponents[1] if not isnoderange and not configmanager.is_node(nodeorrange): raise exc.NotFoundException("Invalid Node") if isnoderange and not (len(pathcomponents) == 3 and pathcomponents[2] == 'abbreviate'): try: nodes = noderange.NodeRange(nodeorrange, configmanager).nodes except Exception as e: raise exc.NotFoundException("Invalid Noderange: " + str(e)) else: nodes = (nodeorrange, ) except IndexError: # doesn't actually have a long enough path # this is enumerating a list of nodes or just empty noderange if isnoderange and operation == "retrieve": return iterate_collections([]) elif isnoderange and operation == "create": inputdata = msg.InputAttributes(pathcomponents, inputdata) return create_noderange(inputdata.attribs, configmanager) elif isnoderange or operation == "delete": raise exc.InvalidArgumentException() if operation == "create": inputdata = msg.InputAttributes(pathcomponents, inputdata) return create_node(inputdata.attribs, configmanager) allnodes = list(configmanager.list_nodes()) try: allnodes.sort(key=noderange.humanify_nodename) except TypeError: allnodes.sort() return iterate_collections(allnodes) if (isnoderange and len(pathcomponents) == 3 and pathcomponents[2] == 'nodes'): # this means that it's a list of relevant nodes nodes = list(nodes) try: nodes.sort(key=noderange.humanify_nodename) except TypeError: nodes.sort() return iterate_collections(nodes) if len(pathcomponents) == 2: iscollection = True else: try: routespec = nested_lookup(noderesources, pathcomponents[2:]) except KeyError: raise exc.NotFoundException("Invalid element requested") if isinstance(routespec, dict): iscollection = True elif isinstance(routespec, PluginCollection): iscollection = False # it is a collection, but plugin defined elif routespec is None: raise exc.InvalidArgumentException( 'Custom interface required for resource') if iscollection: if operation == "delete": return delete_node_collection(pathcomponents, configmanager, isnoderange) elif operation == "retrieve": return enumerate_node_collection(pathcomponents, configmanager) else: raise Exception("TODO here") del pathcomponents[0:2] passvalues = queue.Queue() plugroute = routespec.routeinfo msginputdata = msg.get_input_message(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) else: hfunc = getattr(plugroute['handler'], operation) passvalue = hfunc(nodes=nodes, element=pathcomponents, configmanager=configmanager, inputdata=msginputdata) if isnoderange: return passvalue elif isinstance(passvalue, console.Console): return [passvalue] else: return stripnode(passvalue, nodes[0]) elif 'pluginattrs' in plugroute: nodeattr = configmanager.get_node_attributes( nodes, plugroute['pluginattrs'] + ['collective.manager']) plugpath = None nodesbymanager = {} nodesbyhandler = {} badcollnodes = [] for node in nodes: for attrname in plugroute['pluginattrs']: if attrname in nodeattr[node]: plugpath = nodeattr[node][attrname]['value'] elif 'default' in plugroute: plugpath = plugroute['default'] if plugpath in dispatch_plugins: cfm.check_quorum() manager = nodeattr[node].get('collective.manager', {}).get('value', None) if manager: if collective.get_myname() != manager: if manager not in nodesbymanager: nodesbymanager[manager] = set([node]) else: nodesbymanager[manager].add(node) continue elif list(cfm.list_collective()): badcollnodes.append(node) continue if plugpath: try: hfunc = getattr(pluginmap[plugpath], operation) except KeyError: nodesbyhandler[BadPlugin(node, plugpath).error] = [node] continue if hfunc in nodesbyhandler: nodesbyhandler[hfunc].append(node) else: nodesbyhandler[hfunc] = [node] for bn in badcollnodes: nodesbyhandler[BadCollective(bn).error] = [bn] workers = greenpool.GreenPool() numworkers = 0 for hfunc in nodesbyhandler: numworkers += 1 workers.spawn( addtoqueue, passvalues, hfunc, { 'nodes': nodesbyhandler[hfunc], 'element': pathcomponents, 'configmanager': configmanager, 'inputdata': msginputdata }) for manager in nodesbymanager: numworkers += 1 workers.spawn( addtoqueue, passvalues, dispatch_request, { 'nodes': nodesbymanager[manager], 'manager': manager, 'element': pathcomponents, 'configmanager': configmanager, 'inputdata': inputdata, 'operation': operation, 'isnoderange': isnoderange }) if isnoderange or not autostrip: return iterate_queue(numworkers, passvalues) else: if numworkers > 0: return iterate_queue(numworkers, passvalues, nodes[0]) else: raise exc.NotImplementedException()
def strip_node(self, node): raise exc.NotFoundException(self.error)
def show_info(mac): mac = mac.replace('-', ':') if mac not in known_info: raise exc.NotFoundException(mac + ' not a known mac address') for i in send_discovery_datum(known_info[mac]): yield i
def handle_path(path, operation, configmanager, inputdata=None, autostrip=True): """Given a full path request, return an object. The plugins should generally return some sort of iterator. An exception is made for console/session, which should return a class with connect(), read(), write(bytes), and close() """ pathcomponents = path.split('/') del pathcomponents[0] # discard the value from leading / if pathcomponents[-1] == '': del pathcomponents[-1] if not pathcomponents: # root collection list return enumerate_collections(rootcollections) elif pathcomponents[0] == 'noderange': return handle_node_request(configmanager, inputdata, operation, pathcomponents, autostrip) elif pathcomponents[0] == 'deployment': return handle_deployment(configmanager, inputdata, pathcomponents, operation) elif pathcomponents[0] == 'nodegroups': return handle_nodegroup_request(configmanager, inputdata, pathcomponents, operation) elif pathcomponents[0] == 'nodes': # single node request of some sort return handle_node_request(configmanager, inputdata, operation, pathcomponents, autostrip) elif pathcomponents[0] == 'discovery': return disco.handle_api_request(configmanager, inputdata, operation, pathcomponents) elif pathcomponents[0] == 'networking': return macmap.handle_api_request(configmanager, inputdata, operation, pathcomponents) elif pathcomponents[0] == 'version': return (msg.Attributes(kv={'version': confluent.__version__}), ) elif pathcomponents[0] == 'usergroups': # TODO: when non-administrator accounts exist, # they must only be allowed to see their own user try: usergroup = pathcomponents[1] except IndexError: # it's just users/ if operation == 'create': inputdata = msg.get_input_message(pathcomponents, operation, inputdata, configmanager=configmanager) create_usergroup(inputdata.attribs, configmanager) return iterate_collections(configmanager.list_usergroups(), forcecollection=False) if usergroup not in configmanager.list_usergroups(): raise exc.NotFoundException("Invalid usergroup %s" % usergroup) if operation == 'retrieve': return show_usergroup(usergroup, configmanager) elif operation == 'delete': return delete_usergroup(usergroup, configmanager) elif operation == 'update': inputdata = msg.get_input_message(pathcomponents, operation, inputdata, configmanager=configmanager) update_usergroup(usergroup, inputdata.attribs, configmanager) return show_usergroup(usergroup, configmanager) elif pathcomponents[0] == 'users': # TODO: when non-administrator accounts exist, # they must only be allowed to see their own user try: user = pathcomponents[1] except IndexError: # it's just users/ if operation == 'create': inputdata = msg.get_input_message(pathcomponents, operation, inputdata, configmanager=configmanager) create_user(inputdata.attribs, configmanager) return iterate_collections(configmanager.list_users(), forcecollection=False) if user not in configmanager.list_users(): raise exc.NotFoundException("Invalid user %s" % user) if operation == 'retrieve': return show_user(user, configmanager) elif operation == 'delete': return delete_user(user, configmanager) elif operation == 'update': inputdata = msg.get_input_message(pathcomponents, operation, inputdata, configmanager=configmanager) update_user(user, inputdata.attribs, configmanager) return show_user(user, configmanager) elif pathcomponents[0] == 'events': try: element = pathcomponents[1] except IndexError: if operation != 'retrieve': raise exc.InvalidArgumentException('Target is read-only') return (msg.ChildCollection('decode'), ) if element != 'decode': raise exc.NotFoundException() if operation == 'update': return alerts.decode_alert(inputdata, configmanager) elif pathcomponents[0] == 'discovery': return handle_discovery(pathcomponents[1:], operation, configmanager, inputdata) else: raise exc.NotFoundException()
def handle_read_api_request(pathcomponents, configmanager): # TODO(jjohnson2): discovery core.py api handler design, apply it here # to make this a less tangled mess as it gets extended if len(pathcomponents) == 1: return [ msg.ChildCollection('macs/'), msg.ChildCollection('neighbors/') ] elif pathcomponents[1] == 'neighbors': if len(pathcomponents) == 3 and pathcomponents[-1] == 'by-switch': return [ msg.ChildCollection(x + '/') for x in list_switches(configmanager) ] else: return _handle_neighbor_query(pathcomponents[2:], configmanager) elif len(pathcomponents) == 2: if pathcomponents[-1] == 'macs': return [ msg.ChildCollection(x) for x in ( # 'by-node/', 'by-mac/', 'by-switch/', 'rescan') ] elif pathcomponents[-1] == 'neighbors': return [msg.ChildCollection('by-switch/')] else: raise exc.NotFoundException( 'Unknown networking resource {0}'.format(pathcomponents[-1])) if False and pathcomponents[2] == 'by-node': # TODO: should be list of node names, and then under that 'by-mac' if len(pathcomponents) == 3: return [ msg.ChildCollection(x.replace(':', '-')) for x in util.natural_sort(list(_nodesbymac)) ] elif len(pathcomponents) == 4: macaddr = pathcomponents[-1].replace('-', ':') return dump_macinfo(macaddr) elif pathcomponents[2] == 'by-mac': if len(pathcomponents) == 3: return [ msg.ChildCollection(x.replace(':', '-')) for x in sorted(list(_apimacmap)) ] elif len(pathcomponents) == 4: return dump_macinfo(pathcomponents[-1]) elif pathcomponents[2] == 'by-switch': if len(pathcomponents) == 3: return [ msg.ChildCollection(x + '/') for x in list_switches(configmanager) ] if len(pathcomponents) == 4: return [msg.ChildCollection('by-port/')] if len(pathcomponents) == 5: switchname = pathcomponents[-2] if switchname not in _macsbyswitch: raise exc.NotFoundException( 'No known macs for switch {0}'.format(switchname)) return [ msg.ChildCollection(x.replace('/', '-') + '/') for x in util.natural_sort(list(_macsbyswitch[switchname])) ] if len(pathcomponents) == 6: return [msg.ChildCollection('by-mac/')] if len(pathcomponents) == 7: switchname = pathcomponents[-4] portname = pathcomponents[-2] try: if portname not in _macsbyswitch[switchname]: portname = portname.replace('-', '/') maclist = _macsbyswitch[switchname][portname] except KeyError: foundsomemacs = False if switchname in _macsbyswitch: try: matcher = re.compile(portname) except Exception: raise exc.InvalidArgumentException( 'Invalid regular expression specified') maclist = [] for actualport in _macsbyswitch[switchname]: if bool(matcher.match(actualport)): foundsomemacs = True maclist = maclist + _macsbyswitch[switchname][ actualport] if not foundsomemacs: raise exc.NotFoundException('No known macs for switch {0} ' 'port {1}'.format( switchname, portname)) return [ msg.ChildCollection(x.replace(':', '-')) for x in sorted(maclist) ] if len(pathcomponents) == 8: return dump_macinfo(pathcomponents[-1]) elif pathcomponents[2] == 'rescan': return [msg.KeyValueData({'scanning': mapupdating.locked()})] raise exc.NotFoundException('Unrecognized path {0}'.format( '/'.join(pathcomponents)))
def handle_node_request(configmanager, inputdata, operation, pathcomponents, autostrip=True): iscollection = False routespec = None if pathcomponents[0] == 'noderange': if len(pathcomponents) > 3 and pathcomponents[2] == 'nodes': # transform into a normal looking node request # this does mean we don't see if it is a valid # child, but that's not a goal for the noderange # facility anyway isnoderange = False pathcomponents = pathcomponents[2:] elif len(pathcomponents) == 3 and pathcomponents[2] == 'abbreviate': return abbreviate_noderange(configmanager, inputdata, operation) else: isnoderange = True else: isnoderange = False try: nodeorrange = pathcomponents[1] if not isnoderange and not configmanager.is_node(nodeorrange): raise exc.NotFoundException("Invalid Node") if isnoderange and not (len(pathcomponents) == 3 and pathcomponents[2] == 'abbreviate'): try: nodes = noderange.NodeRange(nodeorrange, configmanager).nodes except Exception as e: raise exc.NotFoundException("Invalid Noderange: " + str(e)) else: nodes = (nodeorrange, ) except IndexError: # doesn't actually have a long enough path # this is enumerating a list of nodes or just empty noderange if isnoderange and operation == "retrieve": return iterate_collections([]) elif isnoderange and operation == "create": inputdata = msg.InputAttributes(pathcomponents, inputdata) return create_noderange(inputdata.attribs, configmanager) elif isnoderange or operation == "delete": raise exc.InvalidArgumentException() if operation == "create": inputdata = msg.InputAttributes(pathcomponents, inputdata) return create_node(inputdata.attribs, configmanager) allnodes = list(configmanager.list_nodes()) try: allnodes.sort(key=noderange.humanify_nodename) except TypeError: allnodes.sort() return iterate_collections(allnodes) if (isnoderange and len(pathcomponents) == 3 and pathcomponents[2] == 'nodes'): # this means that it's a list of relevant nodes nodes = list(nodes) try: nodes.sort(key=noderange.humanify_nodename) except TypeError: nodes.sort() return iterate_collections(nodes) if len(pathcomponents) == 2: iscollection = True else: try: routespec = nested_lookup(noderesources, pathcomponents[2:]) except KeyError: raise exc.NotFoundException("Invalid element requested") if isinstance(routespec, dict): iscollection = True elif isinstance(routespec, PluginCollection): iscollection = False # it is a collection, but plugin defined elif routespec is None: raise exc.InvalidArgumentException( 'Custom interface required for resource') if iscollection: if operation == "delete": return delete_node_collection(pathcomponents, configmanager, isnoderange) elif operation == "retrieve": return enumerate_node_collection(pathcomponents, configmanager) else: raise Exception("TODO here") del pathcomponents[0:2] passvalues = [] plugroute = routespec.routeinfo inputdata = msg.get_input_message(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) else: hfunc = getattr(plugroute['handler'], operation) passvalue = hfunc(nodes=nodes, element=pathcomponents, configmanager=configmanager, inputdata=inputdata) if isnoderange: return passvalue elif isinstance(passvalue, console.Console): return passvalue else: return stripnode(passvalue, nodes[0]) elif 'pluginattrs' in plugroute: nodeattr = configmanager.get_node_attributes(nodes, plugroute['pluginattrs']) plugpath = None if 'default' in plugroute: plugpath = plugroute['default'] nodesbyhandler = {} for node in nodes: for attrname in plugroute['pluginattrs']: if attrname in nodeattr[node]: plugpath = nodeattr[node][attrname]['value'] if plugpath is not None: try: hfunc = getattr(pluginmap[plugpath], operation) except KeyError: nodesbyhandler[BadPlugin(node, plugpath).error] = [node] continue if hfunc in nodesbyhandler: nodesbyhandler[hfunc].append(node) else: nodesbyhandler[hfunc] = [node] for hfunc in nodesbyhandler: passvalues.append( hfunc(nodes=nodesbyhandler[hfunc], element=pathcomponents, configmanager=configmanager, inputdata=inputdata)) if isnoderange or not autostrip: return itertools.chain(*passvalues) else: if len(passvalues) > 0: if isinstance(passvalues[0], console.Console): return passvalues[0] else: return stripnode(passvalues[0], nodes[0]) else: raise exc.NotImplementedException()
def nested_lookup(nestdict, key): try: return reduce(seek_element, key, nestdict) except TypeError: raise exc.NotFoundException("Invalid element requested")