2
0
mirror of https://github.com/xcat2/confluent.git synced 2024-11-26 11:30:23 +00:00

Provide config enabled switch mapping

Wire up the singleton switch search function to a function that
extracts list of switches and relevant auth data from the config
engine.  Add attributes to allow indication by hardware management
port connection.  The OS nics will be added later for in-band discovery,
but that's of limited value until PXE support anyway.

This time, the update function is a generator that yields as a sign to caller
that the mac map has had at least a partial update to be considered.
This commit is contained in:
Jarrod Johnson 2016-06-29 16:32:46 -04:00
parent 4aeb7e1df5
commit b9733b3e0e
3 changed files with 78 additions and 38 deletions

View File

@ -188,12 +188,24 @@ node = {
# 'appliesto': ['vm'],
# },
'hardwaremanagement.manager': {
'description': 'The management address dedicated to this node',
'description': 'The management address dedicated to this node. This '
'is the address of, for example, the Lenovo IMM.',
},
'hardwaremanagement.method': {
'description': 'The method used to perform operations such as power '
'control, get sensor data, get inventory, and so on. '
},
'hardwaremanagement.switch': {
'description': 'The switch to which the hardware manager is connected.'
' Only relevant if using switch based discovery via the'
' hardware manager (Lenovo IMMs and CMMs). Not '
'applicable to Lenovo Flex nodes.'
},
'hardwaremanagement.switchport': {
'description': 'The port of the switch that the hardware manager is '
'connected. See documentation of '
'hardwaremanagement.switch for more detail.'
},
'enclosure.manager': {
'description': "The management device for this node's chassis",
# 'appliesto': ['system'],
@ -202,6 +214,7 @@ node = {
'description': 'The bay in the enclosure, if any',
# 'appliesto': ['system'],
},
# 'enclosure.type': {
# 'description': '''The type of enclosure in use (e.g. IBM BladeCenter,
#IBM Flex)''',
@ -225,19 +238,19 @@ node = {
# 'secret.snmpuser': {
# 'description': 'The user to use for SNMPv3 access to this node',
# },
# 'secret.snmppassphrase': {
# 'description': 'The passphrase to use for SNMPv3 access to this node',
# 'secret.snmppassword': {
# 'description': 'The password to use for SNMPv3 access to this node',
# },
'secret.snmpcommunity': {
'description': ('SNMPv1 community string, it is highly recommended to'
'step up to SNMPv3'),
},
# 'secret.snmplocalizedkey': {
# 'description': ("SNMPv3 key localized to this node's SNMP Engine id"
# 'This can be used in lieu of snmppassphrase to avoid'
# 'retaining the passphrase TODO: document procedure'
# 'to commit passphrase to localized key'),
# },
# 'secret.snmpcommunity': {
# 'description': ('SNMPv1 community string, it is highly recommended to'
# 'step up to SNMPv3'),
# },
# 'secret.adminpassword': {
# 'description': ('The passphrase to apply to local root/administrator '
# 'account. '
@ -249,35 +262,18 @@ node = {
# 'AD')
# },
'secret.ipmikg': {
'description': 'Optional Integrity key for IPMI communication'
'description': 'Optional Integrity key for IPMI communication. This '
'should generally be ignored, as mutual authentication '
'is normally done with the password alone (which is a '
'shared secret in IPMI)'
},
# 'secret.ipmiuser': {
# 'description': ('The username to use to log into IPMI device related '
# 'to the node. For setting username, default '
# 'behavior is to randomize username, for using '
# 'username if not set, USERID is assumed'),
# },
# 'secret.ipmipassphrase': {
# 'description': ('The key to use to authenticate to IPMI device '
# 'related to the node. For setting passphrase, '
# 'default behavior is to randomize passphrase and '
# 'store it here. If going to connect over the '
# 'network and value is not set, PASSW0RD is attempted')
# },
'secret.hardwaremanagementuser': {
'description': ('Username to be set and used by protocols like SSH '
'and HTTP where client provides passphrase over the '
'network. Given the distinct security models betwen '
'this class of protocols and SNMP and IPMI, snmp and '
'ipmi utilize dedicated values.'),
'description': ('The username to use when connecting to the hardware '
'manager'),
},
'secret.hardwaremanagementpassword': {
'description': ('Passphrase to be set and used by protocols like SSH '
'and HTTP, where client sends passphrase over the '
'network. Given distinct security models between '
'this class of protocols, SNMP, and IPMI, SNMP and '
'IPMI are given their own settings with distinct '
'behaviors'),
'description': ('Password to use when connecting to the hardware '
'manager'),
},
'pubkeys.addpolicy': {
'description': ('Policy to use when encountering unknown public '

View File

@ -761,7 +761,9 @@ class ConfigManager(object):
decrypt=self.decrypt)
return nodeobj
def get_node_attributes(self, nodelist, attributes=()):
def get_node_attributes(self, nodelist, attributes=(), decrypt=None):
if decrypt is None:
decrypt = self.decrypt
retdict = {}
relattribs = attributes
if isinstance(nodelist, str) or isinstance(nodelist, unicode):
@ -783,7 +785,7 @@ class ConfigManager(object):
# skipped. The decryption, however, we want to do only on
# demand
nodeobj[attribute] = _decode_attribute(attribute, cfgnodeobj,
decrypt=self.decrypt)
decrypt=decrypt)
retdict[node] = nodeobj
return retdict

View File

@ -33,11 +33,14 @@
import confluent.exceptions as exc
import confluent.snmputil as snmp
import confluent.util as util
import eventlet
from eventlet.greenpool import GreenPool
_macmap = {}
def _map_switch(switch, password, user=None):
def _map_switch(args):
"""Manipulate portions of mac address map relevant to a given switch
"""
@ -53,6 +56,8 @@ def _map_switch(switch, password, user=None):
# .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)
@ -85,10 +90,47 @@ def _map_switch(switch, password, user=None):
ifidx, ifname = vb
ifidx = int(str(ifidx).rsplit('.', 1)[1])
ifnamemap[ifidx] = str(ifname)
localmap = {}
for mac in mactobridge:
localmap[mac] = ifnamemap[bridgetoifmap[mactobridge[mac]]]
print(repr(localmap))
_macmap[mac] = (switch, ifnamemap[bridgetoifmap[mactobridge[mac]]],
util.monotonic_time())
def update_macmap(configmanager):
"""Interrogate switches to build/update mac table
Begin a rebuild process. This process is a generator that will yield
as each switch interrogation completes, allowing a caller to
recheck the cache as results become possible, rather
than having to wait for the process to complete to interrogate.
"""
if configmanager.tenant is not None:
raise exc.ForbiddenRequest('Network topology not available to tenants')
nodelocations = configmanager.get_node_attributes(
configmanager.list_nodes(), ('hardwaremanagement.switch',))
switches = set([])
for node in nodelocations:
cfg = nodelocations[node]
if 'hardwaremanagement.switch' in cfg:
switches.add(cfg['hardwaremanagement.switch']['value'])
switchcfg = configmanager.get_node_attributes(
switches, ('secret.hardwaremanagementuser',
'secret.hardwaremanagementpassword'), decrypt=True)
switchauth = []
for switch in switches:
password = 'public'
user = None
if (switch in switchcfg and
'secret.hardwaremanagementpassword' in switchcfg[switch]):
password = switchcfg[switch]['secret.hardwaremanagementpassword'][
'value']
if 'secret.hardwaremanagementuser' in switchcfg[switch]:
user = switchcfg[switch]['secret.hardwaremanagementuser'][
'value']
switchauth.append((switch, password, user))
pool = GreenPool()
for res in pool.imap(_map_switch, switchauth):
yield res
print(repr(_macmap))
if __name__ == '__main__':