def _webconfignet(self, wc, nodename): cfg = self.configmanager cd = cfg.get_node_attributes(nodename, ['hardwaremanagement.manager']) smmip = cd.get(nodename, {}).get('hardwaremanagement.manager', {}).get('value', None) if smmip and ':' not in smmip: smmip = getaddrinfo(smmip, 0)[0] smmip = smmip[-1][0] if smmip and ':' in smmip: raise exc.NotImplementedException('IPv6 not supported') netconfig = netutil.get_nic_config(cfg, nodename, ip=smmip) netmask = netutil.cidr_to_mask(netconfig['prefix']) setdata = 'set=ifIndex:0,v4DHCPEnabled:0,v4IPAddr:{0},v4NetMask:{1}'.format( smmip, netmask) gateway = netconfig.get('ipv4_gateway', None) if gateway: setdata += ',v4Gateway:{0}'.format(gateway) wc.request('POST', '/data', setdata) rsp = wc.getresponse() rspdata = rsp.read() if '<statusCode>0' not in rspdata: raise Exception("Error configuring SMM Network") return if smmip and ':' in smmip and not smmip.startswith('fe80::'): raise exc.NotImplementedException('IPv6 configuration TODO') if self.ipaddr.startswith('fe80::'): cfg.set_node_attributes( {nodename: { 'hardwaremanagement.manager': self.ipaddr }})
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 get_prefix_len_for_ip(ip): # for now, we'll use the system route table # later may provide for configuration lookup to override the route # table ip = getaddrinfo(ip, 0, socket.AF_INET)[0][-1][0] try: ipn = socket.inet_aton(ip) except socket.error: # For now, assume 64 for ipv6 return 64 # It comes out big endian, regardless of host arch ipn = struct.unpack('>I', ipn)[0] rf = open('/proc/net/route') ri = rf.read() rf.close() ri = ri.split('\n')[1:] for rl in ri: if not rl: continue rd = rl.split('\t') if rd[1] == '00000000': # default gateway, not useful for this continue # don't have big endian to look at, assume that it is host endian maskn = struct.unpack('I', struct.pack('>I', int(rd[7], 16)))[0] netn = struct.unpack('I', struct.pack('>I', int(rd[1], 16)))[0] if ipn & maskn == netn: nbits = 0 while maskn: nbits += 1 maskn = maskn << 1 & 0xffffffff return nbits raise exc.NotImplementedException("Non local addresses not supported")
def _webconfignet(self, wc, nodename): cfg = self.configmanager if 'service:lenovo-smm2' in self.info.get('services', []): # need to enable ipmi for now.. wc.request('POST', '/data', 'set=DoCmd(0x06,0x40,0x01,0x82,0x84)') rsp = wc.getresponse() rsp.read() wc.request('POST', '/data', 'set=DoCmd(0x06,0x40,0x01,0x42,0x44)') rsp = wc.getresponse() rsp.read() cd = cfg.get_node_attributes(nodename, ['hardwaremanagement.manager']) smmip = cd.get(nodename, {}).get('hardwaremanagement.manager', {}).get('value', None) if smmip and ':' not in smmip: smmip = getaddrinfo(smmip, 0)[0] smmip = smmip[-1][0] if smmip and ':' in smmip: raise exc.NotImplementedException('IPv6 not supported') wc.request('POST', '/data', 'get=hostname') rsp = wc.getresponse() rspdata = fromstring(util.stringify(rsp.read())) currip = rspdata.find('netConfig').find('ifConfigEntries').find( 'ifConfig').find('v4IPAddr').text if currip == smmip: return netconfig = netutil.get_nic_config(cfg, nodename, ip=smmip) netmask = netutil.cidr_to_mask(netconfig['prefix']) setdata = 'set=ifIndex:0,v4DHCPEnabled:0,v4IPAddr:{0},v4NetMask:{1}'.format( smmip, netmask) gateway = netconfig.get('ipv4_gateway', None) if gateway: setdata += ',v4Gateway:{0}'.format(gateway) wc.request('POST', '/data', setdata) rsp = wc.getresponse() rspdata = util.stringify(rsp.read()) if '<statusCode>0' not in rspdata: raise Exception("Error configuring SMM Network") return if smmip and ':' in smmip and not smmip.startswith('fe80::'): raise exc.NotImplementedException('IPv6 configuration TODO') if self.ipaddr.startswith('fe80::'): cfg.set_node_attributes( {nodename: { 'hardwaremanagement.manager': self.ipaddr }})
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 __init__(self, events=(), name=None): eventdata = [] self.notnode = name is None for event in events: entry = { 'id': event.get('id', None), 'component': event.get('component', None), 'component_type': event.get('component_type', None), 'event': event.get('event', None), 'severity': event['severity'], 'timestamp': event.get('timestamp', None), 'record_id': event.get('record_id', None), } if event['severity'] not in valid_health_values: raise exc.NotImplementedException('Invalid severity - ' + repr(event['severity'])) eventdata.append(entry) if self.notnode: self.kvpairs = {'events': eventdata} else: self.kvpairs = {name: {'events': eventdata}}
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_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 stripnode(iterablersp, node): for i in iterablersp: if i is None: raise exc.NotImplementedException("Not Implemented") i.strip_node(node) yield i
def _bmcconfig(self, nodename, reset=False, customconfig=None, vc=None): # TODO(jjohnson2): set ip parameters, user/pass, alert cfg maybe # In general, try to use https automation, to make it consistent # between hypothetical secure path and today. creds = self.configmanager.get_node_attributes(nodename, [ 'secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword' ], decrypt=True) user = creds.get(nodename, {}).get('secret.hardwaremanagementuser', {}).get('value', None) passwd = creds.get(nodename, {}).get('secret.hardwaremanagementpassword', {}).get('value', None) try: ic = self._get_ipmicmd() passwd = self.DEFAULT_PASS except pygexc.IpmiException as pi: havecustomcreds = False if user is not None and user != self.DEFAULT_USER: havecustomcreds = True else: user = self.DEFAULT_USER if passwd is not None and passwd != self.DEFAULT_PASS: havecustomcreds = True else: passwd = self.DEFAULT_PASS if havecustomcreds: ic = self._get_ipmicmd(user, passwd) else: raise if vc: ic.register_key_handler(vc) currusers = ic.get_users() lanchan = ic.get_network_channel() userdata = ic.xraw_command(netfn=6, command=0x44, data=(lanchan, 1)) userdata = bytearray(userdata['data']) maxusers = userdata[0] & 0b111111 enabledusers = userdata[1] & 0b111111 lockedusers = userdata[2] & 0b111111 cfg = self.configmanager cd = cfg.get_node_attributes(nodename, [ 'secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword', 'hardwaremanagement.manager' ], True) cd = cd.get(nodename, {}) if ('secret.hardwaremanagementuser' not in cd or 'secret.hardwaremanagementpassword' not in cd): raise exc.TargetEndpointBadCredentials( 'secret.hardwaremanagementuser and/or ' 'secret.hardwaremanagementpassword was not configured') newuser = cd['secret.hardwaremanagementuser']['value'] newpass = cd['secret.hardwaremanagementpassword']['value'] for uid in currusers: if currusers[uid]['name'] == newuser: # Use existing account that has been created newuserslot = uid if newpass != passwd: # don't mess with existing if no change ic.set_user_password(newuserslot, password=newpass) ic = self._get_ipmicmd(user, passwd) if vc: ic.register_key_handler(vc) break else: newuserslot = lockedusers + 1 if newuserslot < 2: newuserslot = 2 if newpass != passwd: # don't mess with existing if no change ic.set_user_password(newuserslot, password=newpass) ic.set_user_name(newuserslot, newuser) if havecustomcreds: ic = self._get_ipmicmd(user, passwd) if vc: ic.register_key_handler(vc) #We are remote operating on the account we are #using, no need to try to set user access #ic.set_user_access(newuserslot, lanchan, # privilege_level='administrator') # Now to zap others for uid in currusers: if uid != newuserslot: if uid <= lockedusers: # we cannot delete, settle for disable ic.disable_user(uid, 'disable') else: # lead with the most critical thing, removing user access ic.set_user_access(uid, channel=None, callback=False, link_auth=False, ipmi_msg=False, privilege_level='no_access') # next, try to disable the password ic.set_user_password(uid, mode='disable', password=None) # ok, now we can be less paranoid try: ic.user_delete(uid) except pygexc.IpmiException as ie: if ie.ipmicode != 0xd5: # some response to the 0xff # name... # the user will remain, but that is life raise if customconfig: customconfig(ic) if ('hardwaremanagement.manager' in cd and cd['hardwaremanagement.manager']['value'] and not cd['hardwaremanagement.manager']['value'].startswith( 'fe80::')): newip = cd['hardwaremanagement.manager']['value'] newipinfo = getaddrinfo(newip, 0)[0] # This getaddrinfo is repeated in get_nic_config, could be # optimized, albeit with a more convoluted api.. newip = newipinfo[-1][0] if ':' in newip: raise exc.NotImplementedException('IPv6 remote config TODO') netconfig = netutil.get_nic_config(cfg, nodename, ip=newip) plen = netconfig['prefix'] newip = '{0}/{1}'.format(newip, plen) currcfg = ic.get_net_configuration() if currcfg['ipv4_address'] != newip: # do not change the ipv4_config if the current config looks # like it is already accurate ic.set_net_configuration( ipv4_address=newip, ipv4_configuration='static', ipv4_gateway=netconfig['ipv4_gateway']) elif self.ipaddr.startswith('fe80::'): cfg.set_node_attributes( {nodename: { 'hardwaremanagement.manager': self.ipaddr }}) else: raise exc.TargetEndpointUnreachable( 'hardwaremanagement.manager must be set to desired address') if reset: ic.reset_bmc() return ic
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 config(self, nodename): self.nodename = nodename creds = self.configmanager.get_node_attributes( nodename, ['secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword', 'hardwaremanagement.manager', 'hardwaremanagement.method', 'console.method'], True) cd = creds.get(nodename, {}) user, passwd, _ = self.get_node_credentials( nodename, creds, self.DEFAULT_USER, self.DEFAULT_PASS) user = util.stringify(user) passwd = util.stringify(passwd) self.targuser = user self.targpass = passwd wc = self._get_wc() wc.set_header('X-CSRFTOKEN', self.csrftok) curruserinfo = {} authupdate = False wc.set_header('Content-Type', 'application/json') if user != self.curruser: authupdate = True if not curruserinfo: curruserinfo = wc.grab_json_response('/api/settings/users') authchg = curruserinfo[1] authchg['name'] = user if passwd != self.currpass: authupdate = True if not curruserinfo: curruserinfo = wc.grab_json_response('/api/settings/users') authchg = curruserinfo[1] authchg['changepassword'] = 0 authchg['password_size'] = 'bytes_20' authchg['password'] = passwd authchg['confirm_password'] = passwd if authupdate: rsp, status = wc.grab_json_response_with_status('/api/settings/users/2', authchg, method='PUT') if (cd.get('hardwaremanagement.method', {}).get('value', 'ipmi') != 'redfish' or cd.get('console.method', {}).get('value', None) == 'ipmi'): # IPMI must be enabled per user config wc.grab_json_response('/api/settings/ipmilanconfig', { 'ipv4_enable': 1, 'ipv6_enable': 1, 'uncheckedipv4lanEnable': 0, 'uncheckedipv6lanEnable': 0, 'checkedipv4lanEnable': 1, 'checkedipv6lanEnable': 1}) if ('hardwaremanagement.manager' in cd and cd['hardwaremanagement.manager']['value'] and not cd['hardwaremanagement.manager']['value'].startswith( 'fe80::')): newip = cd['hardwaremanagement.manager']['value'] newipinfo = getaddrinfo(newip, 0)[0] newip = newipinfo[-1][0] if ':' in newip: raise exc.NotImplementedException('IPv6 remote config TODO') currnet = wc.grab_json_response('/api/settings/network') for net in currnet: if net['channel_number'] == self.channel and net['lan_enable'] == 0: # ignore false indication and switch to 8 (dedicated) self.channel = 8 if net['channel_number'] == self.channel: # we have found the interface to potentially manipulate if net['ipv4_address'] != newip: netconfig = netutil.get_nic_config(self.configmanager, nodename, ip=newip) newmask = netutil.cidr_to_mask(netconfig['prefix']) net['ipv4_address'] = newip net['ipv4_subnet'] = newmask if netconfig['ipv4_gateway']: net['ipv4_gateway'] = netconfig['ipv4_gateway'] net['ipv4_dhcp_enable'] = 0 rsp, status = wc.grab_json_response_with_status( '/api/settings/network/{0}'.format(net['id']), net, method='PUT') break elif self.ipaddr.startswith('fe80::'): self.configmanager.set_node_attributes( {nodename: {'hardwaremanagement.manager': self.ipaddr}}) else: raise exc.TargetEndpointUnreachable( 'hardwaremanagement.manager must be set to desired address (No IPv6 Link Local detected)') rsp, status = wc.grab_json_response_with_status('/api/session', method='DELETE')
def config(self, nodename, reset=False): self.nodename = nodename # TODO(jjohnson2): set ip parameters, user/pass, alert cfg maybe # In general, try to use https automation, to make it consistent # between hypothetical secure path and today. dpp = self.configmanager.get_node_attributes( nodename, 'discovery.passwordrules') strruleset = dpp.get(nodename, {}).get( 'discovery.passwordrules', {}).get('value', '') wc = self.wc creds = self.configmanager.get_node_attributes( self.nodename, ['secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword'], decrypt=True) user, passwd, isdefault = self.get_node_credentials(nodename, creds, 'USERID', 'PASSW0RD') self.set_password_policy(strruleset, wc) if self._atdefaultcreds: if isdefault and self.tmppasswd: raise Exception( 'Request to use default credentials, but refused by target after it has been changed to {0}'.format(self.tmppasswd)) if not isdefault: self._setup_xcc_account(user, passwd, wc) self._convert_sha256account(user, passwd, wc) cd = self.configmanager.get_node_attributes( nodename, ['secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword', 'hardwaremanagement.manager', 'hardwaremanagement.method', 'console.method'], True) cd = cd.get(nodename, {}) if (cd.get('hardwaremanagement.method', {}).get('value', 'ipmi') != 'redfish' or cd.get('console.method', {}).get('value', None) == 'ipmi'): nwc = wc.dupe() nwc.set_basic_credentials(self._currcreds[0], self._currcreds[1]) rsp = nwc.grab_json_response('/redfish/v1/Managers/1/NetworkProtocol') if not rsp.get('IPMI', {}).get('ProtocolEnabled', True): # User has indicated IPMI support, but XCC is currently disabled # change XCC to be consistent _, _ = nwc.grab_json_response_with_status( '/redfish/v1/Managers/1/NetworkProtocol', {'IPMI': {'ProtocolEnabled': True}}, method='PATCH') if ('hardwaremanagement.manager' in cd and cd['hardwaremanagement.manager']['value'] and not cd['hardwaremanagement.manager']['value'].startswith( 'fe80::')): newip = cd['hardwaremanagement.manager']['value'] newipinfo = getaddrinfo(newip, 0)[0] newip = newipinfo[-1][0] if ':' in newip: raise exc.NotImplementedException('IPv6 remote config TODO') netconfig = netutil.get_nic_config(self.configmanager, nodename, ip=newip) newmask = netutil.cidr_to_mask(netconfig['prefix']) currinfo = wc.grab_json_response('/api/providers/logoninfo') currip = currinfo.get('items', [{}])[0].get('ipv4_address', '') # do not change the ipv4_config if the current config looks right already if currip != newip: statargs = { 'ENET_IPv4Ena': '1', 'ENET_IPv4AddrSource': '0', 'ENET_IPv4StaticIPAddr': newip, 'ENET_IPv4StaticIPNetMask': newmask } if netconfig['ipv4_gateway']: statargs['ENET_IPv4GatewayIPAddr'] = netconfig['ipv4_gateway'] wc.grab_json_response('/api/dataset', statargs) elif self.ipaddr.startswith('fe80::'): self.configmanager.set_node_attributes( {nodename: {'hardwaremanagement.manager': self.ipaddr}}) else: raise exc.TargetEndpointUnreachable( 'hardwaremanagement.manager must be set to desired address (No IPv6 Link Local detected)') wc.grab_json_response('/api/providers/logout') ff = self.info.get('attributes', {}).get('enclosure-form-factor', '') if ff not in ('dense-computing', [u'dense-computing']): return enclosureuuid = self.info.get('attributes', {}).get('chassis-uuid', [None])[0] if enclosureuuid: enclosureuuid = enclosureuuid.lower() em = self.configmanager.get_node_attributes(nodename, 'enclosure.manager') em = em.get(nodename, {}).get('enclosure.manager', {}).get( 'value', None) # ok, set the uuid of the manager... if em: self.configmanager.set_node_attributes( {em: {'id.uuid': enclosureuuid}})
def _map_switch_backend(args): """Manipulate portions of mac address map relevant to a given switch """ # 1.3.6.1.2.1.17.7.1.2.2.1.2 - mactoindex (qbridge - preferred) # if not, check for cisco and if cisco, build list of all relevant vlans: # .1.3.6.1.4.1.9.9.46.1.6.1.1.5 - trunk port vlan map (cisco only) # .1.3.6.1.4.1.9.9.68.1.2.2.1.2 - access port vlan map (cisco only) # if cisco, vlan community string indexed or snmpv3 contest for: # 1.3.6.1.2.1.17.4.3.1.2 - mactoindx (bridge - low-end switches and cisco) # .1.3.6.1.2.1.17.1.4.1.2 - bridge index to if index map # no vlan index or context for: # .1.3.6.1.2.1.31.1.1.1.1 - ifName... but some switches don't do it # .1.3.6.1.2.1.2.2.1.2 - ifDescr, usually useless, but a # fallback if ifName is empty # global _macmap switch, password, user = args haveqbridge = False mactobridge = {} conn = snmp.Session(switch, password, user) for vb in conn.walk('1.3.6.1.2.1.17.7.1.2.2.1.2'): haveqbridge = True oid, bridgeport = vb if not bridgeport: continue oid = str(oid).rsplit('.', 6) # if 7, then oid[1] would be vlan id macaddr = '{0:02x}:{1:02x}:{2:02x}:{3:02x}:{4:02x}:{5:02x}'.format( *([int(x) for x in oid[-6:]])) mactobridge[macaddr] = int(bridgeport) if not haveqbridge: raise exc.NotImplementedException('TODO: Bridge-MIB without QBRIDGE') bridgetoifmap = {} for vb in conn.walk('1.3.6.1.2.1.17.1.4.1.2'): bridgeport, ifidx = vb bridgeport = int(str(bridgeport).rsplit('.', 1)[1]) bridgetoifmap[bridgeport] = int(ifidx) ifnamemap = {} havenames = False for vb in conn.walk('1.3.6.1.2.1.31.1.1.1.1'): ifidx, ifname = vb if not ifname: continue havenames = True ifidx = int(str(ifidx).rsplit('.', 1)[1]) ifnamemap[ifidx] = str(ifname) if not havenames: for vb in conn.walk('1.3.6.1.2.1.2.2.1.2'): ifidx, ifname = vb ifidx = int(str(ifidx).rsplit('.', 1)[1]) ifnamemap[ifidx] = str(ifname) maccounts = {} for mac in mactobridge: ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]] if ifname not in maccounts: maccounts[ifname] = 1 else: maccounts[ifname] += 1 _macsbyswitch[switch] = {} for mac in mactobridge: # We want to merge it so that when a mac appears in multiple # places, it is captured. ifname = ifnamemap[bridgetoifmap[mactobridge[mac]]] if mac in _macmap: _macmap[mac].append((switch, ifname, maccounts[ifname])) else: _macmap[mac] = [(switch, ifname, maccounts[ifname])] if ifname in _macsbyswitch[switch]: _macsbyswitch[switch][ifname].append(mac) else: _macsbyswitch[switch][ifname] = [mac] nodename = _nodelookup(switch, ifname) if nodename is not None: if mac in _nodesbymac and _nodesbymac[mac] != nodename: log.log({ 'warning': '{0} and {1} described by ambiguous' ' switch topology values'.format(nodename, _nodesbymac[mac]) }) _nodesbymac[mac] = nodename