2
0
mirror of https://github.com/xcat2/confluent.git synced 2026-08-05 10:17:51 +00:00

Add node operations against Nexus switch

This enables the commands to work that one would expect.
This commit is contained in:
Jarrod Johnson
2025-03-28 13:34:03 -04:00
parent 7419dbcf71
commit 2514507b87
2 changed files with 113 additions and 23 deletions
+18 -23
View File
@@ -20,7 +20,10 @@ def add_sensedata(component, sensedata, name=None):
if units == 'Celsius':
units = '°C'
senseinfo['units'] = units
senseinfo['health'] = _healthmap.get(attrs['operSt'], attrs['operSt'])
senseinfo['health'] = _healthmap.get(attrs['operSt'], 'unknown')
if senseinfo['health'] == 'unknown':
print(senseinfo['health'] + ' not recognized')
senseinfo['health'] = 'critical'
elif 'eqptFtSlot' in component:
attrs = component['eqptFtSlot']['attributes']
name = '{} {}'.format(attrs['descr'], attrs['physId'])
@@ -52,6 +55,8 @@ def add_sensedata(component, sensedata, name=None):
senseinfo = {}
elif 'eqptPsuSlot' in component:
attrs = component['eqptPsuSlot']['attributes']
senseinfo['value'] = None
senseinfo['units'] = None
senseinfo['name'] = 'PSU Slot {}'.format(attrs['physId'])
senseinfo['health'] = 'ok'
senseinfo['states'] = ['Present']
@@ -66,10 +71,6 @@ def add_sensedata(component, sensedata, name=None):
add_sensedata(child, sensedata, name)
class NxApiClient:
def __init__(self, switch, user, password, configmanager):
self.cachedurls = {}
@@ -104,19 +105,6 @@ class NxApiClient:
firmdata['BIOS'] = {'version': attrs['biosVersion'], 'date': attrs['biosCompileTime']}
return firmdata
def get_serial(self):
for imdata in self.grab_imdata('/api/mo/sys/ch.json'):
for keyn in imdata:
currinfo = imdata[keyn]
model = currinfo.get('model', 'Unknown')
serial = currinfo.get('ser', 'Unknown')
modelname = currinfo.get('descr', 'Uknonwn')
self.wc.grab_json_response_with_status('/api/mo/sys.json')
rsp['imdata'][0]['topSystem']['attributes'][serial]
def get_sensors(self):
sensedata = []
for imdata in self.grab_imdata('/api/mo/sys/ch.json?rsp-subtree=full'):
@@ -125,6 +113,18 @@ class NxApiClient:
add_sensedata(component, sensedata)
return sensedata
def get_health(self):
healthdata = {'health': 'ok', 'sensors': []}
for sensor in self.get_sensors():
currhealth = sensor.get('health', 'ok')
if currhealth != 'ok':
healthdata['sensors'].append(sensor)
if sensor['health'] == 'critical':
healthdata['health'] = 'critical'
elif sensor['health'] == 'warning' and healthdata['health'] != 'critical':
healthdata['health'] = 'warning'
return healthdata
def get_inventory(self):
invdata = []
for imdata in self.grab_imdata('/api/mo/sys/ch.json?rsp-subtree=full'):
@@ -155,11 +155,6 @@ class NxApiClient:
invdata.append(invinfo)
return invdata
def grab(self, url, cache=True, retry=True):
if cache is True:
cache = 1
@@ -0,0 +1,95 @@
import confluent.networking.nxapi as nxapi
import eventlet
import eventlet.queue as queue
import eventlet.greenpool as greenpool
import confluent.messages as msg
import traceback
def retrieve_node(node, element, user, pwd, configmanager, inputdata, results):
try:
retrieve_node_backend(node, element, user, pwd, configmanager, inputdata, results)
except Exception as e:
print(traceback.format_exc())
print(repr(e))
def simplify_name(name):
return name.lower().replace(' ', '_').replace('/', '-').replace(
'_-_', '-')
def retrieve_node_backend(node, element, user, pwd, configmanager, inputdata, results):
cli = nxapi.NxApiClient(node, user, pwd, configmanager)
if element == ['power', 'state']: # client initted successfully, must be on
results.put(msg.PowerState(node, 'on'))
elif element == ['health', 'hardware']:
hinfo = cli.get_health()
results.put(msg.HealthSummary(hinfo.get('health', 'unknown'), name=node))
results.put(msg.SensorReadings(hinfo.get('sensors', []), name=node))
elif element[:3] == ['inventory', 'hardware', 'all']:
if len(element) == 3:
results.put(msg.ChildCollection('all'))
return
invinfo = cli.get_inventory()
if invinfo:
results.put(msg.KeyValueData({'inventory': invinfo}, node))
elif element[:3] == ['inventory', 'firmware', 'all']:
if len(element) == 3:
results.put(msg.ChildCollection('all'))
return
fwinfo = []
for fwnam, fwdat in cli.get_firmware().items():
fwinfo.append({fwnam: fwdat})
if fwinfo:
results.put(msg.Firmware(fwinfo, node))
elif element == ['sensors', 'hardware', 'all']:
sensors = cli.get_sensors()
for sensor in sensors:
results.put(msg.ChildCollection(simplify_name(sensor['name'])))
elif element[:3] == ['sensors', 'hardware', 'all']:
sensors = cli.get_sensors()
for sensor in sensors:
if element[-1] == 'all' or simplify_name(sensor['name']) == element[-1]:
results.put(msg.SensorReadings([sensor], node))
else:
print(repr(element))
def retrieve(nodes, element, configmanager, inputdata):
results = queue.LightQueue()
workers = set([])
creds = configmanager.get_node_attributes(
nodes, ['secret.hardwaremanagementuser', 'secret.hardwaremanagementpassword'], decrypt=True)
for node in nodes:
cred = creds.get(node, {})
user = cred.get('secret.hardwaremanagementuser', {}).get('value')
pwd = cred.get('secret.hardwaremanagementpassword', {}).get('value')
try:
user = user.decode()
pwd = pwd.decode()
except Exception:
pass
if not user or not pwd:
yield msg.ConfluentTargetInvalidCredentials(node)
continue
workers.add(eventlet.spawn(retrieve_node, node, element, user, pwd, configmanager, inputdata, results))
while workers:
try:
datum = results.get(block=True, timeout=10)
while datum:
if datum:
yield datum
datum = results.get_nowait()
except queue.Empty:
pass
eventlet.sleep(0.001)
for t in list(workers):
if t.dead:
workers.discard(t)
try:
while True:
datum = results.get_nowait()
if datum:
yield datum
except queue.Empty:
pass