def _dump_locations(info, macaddr, nodename=None): yield msg.KeyValueData({'possiblenode': nodename, 'mac': macaddr}) retdata = {} portinfo = [] for location in info: portinfo.append({'switch': location[0], 'port': location[1], 'macsonport': location[2]}) retdata['ports'] = sorted(portinfo, key=lambda x: x['macsonport'], reverse=True) yield msg.KeyValueData(retdata)
def send_discovery_datum(info): addresses = info.get('addresses', []) if info['handler'] == pxeh: enrich_pxe_info(info) yield msg.KeyValueData({'nodename': info.get('nodename', '')}) yield msg.KeyValueData({'ipaddrs': [x[0] for x in addresses]}) sn = info.get('serialnumber', '') mn = info.get('modelnumber', '') uuid = info.get('uuid', '') if uuid: relatedmacs = [] for mac in known_uuids.get(uuid, {}): if mac and mac != info.get('hwaddr', ''): relatedmacs.append(mac) if relatedmacs: yield msg.KeyValueData({'relatedmacs': relatedmacs}) yield msg.KeyValueData({'serialnumber': sn}) yield msg.KeyValueData({'modelnumber': mn}) yield msg.KeyValueData({'uuid': uuid}) if 'enclosure.bay' in info: yield msg.KeyValueData({'bay': int(info['enclosure.bay'])}) yield msg.KeyValueData({'macs': [info.get('hwaddr', '')]}) types = [] for infotype in info.get('services', []): if infotype in servicenames: types.append(servicenames[infotype]) yield msg.KeyValueData({'types': types})
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 read_inventory(self, component): invitems = [] if component == 'all': for invdata in self.ipmicmd.get_inventory(): if invdata[1] is None: newinf = {'present': False, 'information': None} else: sanitize_invdata(invdata[1]) newinf = {'present': True, 'information': invdata[1]} newinf['name'] = invdata[0] invitems.append(newinf) else: self.make_inventory_map() compname = self.invmap.get(component, None) if compname is None: self.output.put(msg.ConfluentTargetNotFound()) return invdata = self.ipmicmd.get_inventory_of_component(compname) if invdata is None: newinf = {'present': False, 'information': None} else: sanitize_invdata(invdata) newinf = {'present': True, 'information': invdata} newinf['name'] = compname invitems.append(newinf) newinvdata = {'inventory': invitems} self.output.put(msg.KeyValueData(newinvdata, self.node))
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') mac = _get_mac_from_query(pathcomponents) info = known_info[mac] if info['handler'] is None: raise exc.NotImplementedException('Unable to {0} to {1}'.format( operation, '/'.join(pathcomponents))) handler = info['handler'].NodeHandler(info, configmanager) eval_node(configmanager, handler, info, inputdata['node'], manual=True) return [msg.AssignedResource(inputdata['node'])] elif operation == 'delete': mac = _get_mac_from_query(pathcomponents) del known_info[mac] return [msg.DeletedResource(mac)] raise exc.NotImplementedException('Unable to {0} to {1}'.format( operation, '/'.join(pathcomponents)))
def list_updates(nodes, tenant, element, type='firmware'): showmode = False if type == 'mediaupload': myparty = uploadsbytarget verb = 'upload' else: myparty = updatesbytarget verb = 'update' if type == 'firmware': specificlen = 4 else: specificlen = 2 if len(element) > specificlen: showmode = True upid = element[-1] for node in nodes: if showmode: try: updater = myparty[(node, tenant)][upid] except KeyError: raise exc.NotFoundException( 'No matching {0} process found'.format(verb)) yield msg.KeyValueData(updater.progress, name=node) else: for updateid in myparty.get((node, tenant), {}): yield msg.ChildCollection(updateid)
def _expand_expression(nodes, configmanager, inputdata): expression = inputdata.get_attributes(list(nodes)[0]) if type(expression) is dict: expression = expression['expression'] if type(expression) is dict: expression = expression['expression'] for expanded in configmanager.expand_attrib_expression(nodes, expression): yield msg.KeyValueData({'value': expanded[1]}, expanded[0])
def retrieve_inventory(configmanager, creds, node, results, element): if len(element) == 3: results.put(msg.ChildCollection('all')) results.put(msg.ChildCollection('system')) return wc = WebClient(node, configmanager, creds) invinfo = wc.fetch('/affluent/inventory/hardware/all', results) if invinfo: results.put(msg.KeyValueData(invinfo, node))
def handle_api_request(configmanager, inputdata, operation, pathcomponents): if operation == 'retrieve': return handle_read_api_request(pathcomponents) if (operation in ('update', 'create') and pathcomponents == ['networking', 'macs', 'rescan']): if inputdata != {'rescan': 'start'}: raise exc.InvalidArgumentException() eventlet.spawn_n(rescan, configmanager) return [msg.KeyValueData({'rescan': 'started'})] raise exc.NotImplementedException( 'Operation {0} on {1} not implemented'.format( operation, '/'.join(pathcomponents)))
def abbreviate_noderange(configmanager, inputdata, operation): if operation != 'create': raise exc.InvalidArgumentException( 'Must be a create with nodes in list') if 'nodes' not in inputdata: raise exc.InvalidArgumentException( 'Must be given list of nodes under key named nodes') if isinstance(inputdata['nodes'], str) or isinstance( inputdata['nodes'], unicode): inputdata['nodes'] = inputdata['nodes'].split(',') return (msg.KeyValueData({ 'noderange': noderange.ReverseNodeRange(inputdata['nodes'], configmanager).noderange }), )
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 _expand_expression(nodes, configmanager, inputdata): expression = inputdata.get_attributes(list(nodes)[0]) if type(expression) is dict: expression = expression['expression'] if type(expression) is dict: expression = expression['expression'] pernodeexpressions = {} try: for expanded in configmanager.expand_attrib_expression( nodes, expression): pernodeexpressions[expanded[0]] = expanded[1] for node in util.natural_sort(pernodeexpressions): yield msg.KeyValueData({'value': pernodeexpressions[node]}, node) except ValueError as e: raise exc.InvalidArgumentException(str(e))
def _expand_expression(nodes, configmanager, inputdata): expression = inputdata.get_attributes(list(nodes)[0]) if type(expression) is dict: expression = expression['expression'] if type(expression) is dict: expression = expression['expression'] pernodeexpressions = {} try: for expanded in configmanager.expand_attrib_expression( nodes, expression): pernodeexpressions[expanded[0]] = expanded[1] for node in util.natural_sort(pernodeexpressions): yield msg.KeyValueData({'value': pernodeexpressions[node]}, node) except (SyntaxError, ValueError) as e: raise exc.InvalidArgumentException( 'Bad confluent expression syntax (must use "{{" and "}}" if not ' 'desiring confluent expansion): ' + str(e))
def handle_autosense_config(operation, inputdata): autosense = cfm.get_global('discovery.autosense') autosense = autosense or autosense is None if operation == 'retrieve': yield msg.KeyValueData({'enabled': autosense}) elif operation == 'update': enabled = inputdata['enabled'] if type(enabled) in (unicode, str): enabled = enabled.lower() in ('true', '1', 'y', 'yes', 'enable', 'enabled') if autosense == enabled: return cfm.set_global('discovery.autosense', enabled) if enabled: start_autosense() else: stop_autosense()
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 if pathcomponents == ['discovery', 'rescan']: return (msg.KeyValueData({'scanning': bool(scanner)}),) 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')) dirlist.append(msg.ChildCollection('autosense')) 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 read_inventory(self, component): errorneeded = False try: invitems = [] if component == 'all': for invdata in self.ipmicmd.get_inventory(): if invdata[1] is None: newinf = {'present': False, 'information': None} else: sanitize_invdata(invdata[1]) newinf = {'present': True, 'information': invdata[1]} newinf['name'] = invdata[0] invitems.append(newinf) else: self.make_inventory_map() compname = self.invmap.get(component, None) if compname is None: self.output.put(msg.ConfluentTargetNotFound()) return invdata = self.ipmicmd.get_inventory_of_component(compname) if invdata is None: newinf = {'present': False, 'information': None} else: sanitize_invdata(invdata) newinf = {'present': True, 'information': invdata} newinf['name'] = compname invitems.append(newinf) except ssl.SSLEOFError: errorneeded = msg.ConfluentNodeError( self.node, 'Unable to communicate with the https server on ' 'the target BMC while trying to read extended ' 'information') except exc.PubkeyInvalid: errorneeded = msg.ConfluentNodeError( self.node, 'Extended information unavailable, mismatch detected between ' 'target certificate fingerprint and ' 'pubkeys.tls_hardwaremanager attribute') newinvdata = {'inventory': invitems} self.output.put(msg.KeyValueData(newinvdata, self.node)) if errorneeded: self.output.put(errorneeded)
def retrieve_inventory(configmanager, creds, node, results, element): if len(element) == 3: results.put(msg.ChildCollection('all')) results.put(msg.ChildCollection('system')) return wc = cnos_login(node, configmanager, creds) sysinfo = wc.grab_json_response('/nos/api/sysinfo/inventory') invinfo = { 'inventory': [{ 'name': 'System', 'present': True, 'information': { 'Product name': sysinfo['Model'], 'Serial Number': sysinfo['Electronic Serial Number'], 'Board Serial Number': sysinfo['Serial Number'], 'Manufacturer': 'Lenovo', 'Model': sysinfo['Machine Type Model'], 'FRU Number': sysinfo['FRU'].strip(), } }] } results.put(msg.KeyValueData(invinfo, node))
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, 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 get_importing_status(importkey): yield msg.KeyValueData(importing[importkey].progress)
def _dump_neighbordatum(info): return [msg.KeyValueData(info)]