Exemplo n.º 1
0
 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
             }})
Exemplo n.º 2
0
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)))
Exemplo n.º 3
0
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")
Exemplo n.º 4
0
 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
             }})
Exemplo n.º 5
0
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)))
Exemplo n.º 6
0
 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}}
Exemplo n.º 7
0
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)))
Exemplo n.º 8
0
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()
Exemplo n.º 9
0
def stripnode(iterablersp, node):
    for i in iterablersp:
        if i is None:
            raise exc.NotImplementedException("Not Implemented")
        i.strip_node(node)
        yield i
Exemplo n.º 10
0
 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
Exemplo n.º 11
0
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()
Exemplo n.º 12
0
 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')
Exemplo n.º 13
0
 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}})
Exemplo n.º 14
0
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