mirror of
https://github.com/xcat2/confluent.git
synced 2026-09-02 15:36:05 +00:00
Implement the redfish resources that called missing methods
Five resources called methods that do not exist on the redfish client, so each answered with an internal error naming the missing attribute: the leds, the management controller identifier, the domain name, the remote kvm licence and the alert destinations. Implement the first four from the manager network protocol, the graphical console and the chassis indicator. Alert destinations stay unimplemented on purpose. Redfish describes where to send events with EventService subscriptions, which is a different model from the numbered PET destinations this resource was built around, so say so and drop the code that could never run. The location resource fetched its data and discarded it, so a read produced no output whatsoever.
This commit is contained in:
@@ -1157,6 +1157,107 @@ class Command(object):
|
||||
await self._do_web_request(await self.get_bmcnicurl(),
|
||||
{'HostName': hostname}, 'PATCH', etag='*')
|
||||
|
||||
async def _netprotocolurl(self):
|
||||
bmcinfo = await self._do_web_request(await self.get_bmcurl())
|
||||
netprotocols = bmcinfo.get('NetworkProtocol', {}).get('@odata.id', None)
|
||||
if not netprotocols:
|
||||
raise exc.UnsupportedFunctionality(
|
||||
'This platform does not describe its manager network protocols')
|
||||
return netprotocols
|
||||
|
||||
async def get_mci(self):
|
||||
"""Get the management controller identifier
|
||||
|
||||
Redfish has no separate identifier for a management controller the way
|
||||
ipmi does, and the platforms that offer both report the same string for
|
||||
each, so use the name the manager answers to.
|
||||
"""
|
||||
netcfg = await self._do_web_request(await self._netprotocolurl())
|
||||
name = netcfg.get('HostName', None)
|
||||
if name is None:
|
||||
raise exc.UnsupportedFunctionality(
|
||||
'This platform does not report a manager identifier')
|
||||
return name
|
||||
|
||||
async def set_mci(self, mci):
|
||||
await self._do_web_request(await self._netprotocolurl(),
|
||||
{'HostName': mci}, method='PATCH', etag='*')
|
||||
|
||||
async def get_domain_name(self):
|
||||
netcfg = await self._do_web_request(await self._netprotocolurl())
|
||||
fqdn = netcfg.get('FQDN', None)
|
||||
if not fqdn:
|
||||
return ''
|
||||
# The fqdn is the manager name with the domain appended, and only the
|
||||
# domain part is wanted here
|
||||
hostname = netcfg.get('HostName', None)
|
||||
if hostname and fqdn.startswith(hostname + '.'):
|
||||
return fqdn[len(hostname) + 1:]
|
||||
return fqdn.partition('.')[2]
|
||||
|
||||
async def set_domain_name(self, domain):
|
||||
netprotocols = await self._netprotocolurl()
|
||||
netcfg = await self._do_web_request(netprotocols)
|
||||
hostname = netcfg.get('HostName', '')
|
||||
fqdn = '{0}.{1}'.format(hostname, domain) if domain else hostname
|
||||
await self._do_web_request(netprotocols, {'FQDN': fqdn},
|
||||
method='PATCH', etag='*')
|
||||
|
||||
async def get_remote_kvm_available(self):
|
||||
bmcinfo = await self._do_web_request(await self.get_bmcurl())
|
||||
gconsole = bmcinfo.get('GraphicalConsole', {})
|
||||
return bool(gconsole.get('ServiceEnabled', False))
|
||||
|
||||
_ledstatusmap = {
|
||||
'Lit': 'On',
|
||||
'Blinking': 'Blink',
|
||||
'Off': 'Off',
|
||||
}
|
||||
|
||||
async def get_leds(self):
|
||||
"""Get LED status information
|
||||
|
||||
Standard redfish only describes the identify indicator, so that is all a
|
||||
platform without an oem specific view of its leds can report.
|
||||
"""
|
||||
sysinfo = await self.sysinfo()
|
||||
seen = False
|
||||
for chassis in sysinfo.get('Links', {}).get('Chassis', []):
|
||||
chassisinfo = await self._do_web_request(chassis['@odata.id'])
|
||||
state = chassisinfo.get('IndicatorLED', None)
|
||||
if state is None:
|
||||
continue
|
||||
seen = True
|
||||
yield ('identify', {'status': self._ledstatusmap.get(state, state)})
|
||||
break
|
||||
if not seen and sysinfo.get('IndicatorLED', None) is not None:
|
||||
state = sysinfo['IndicatorLED']
|
||||
yield ('identify', {'status': self._ledstatusmap.get(state, state)})
|
||||
|
||||
# A firmware inventory entry says what it belongs to with RelatedItem, so
|
||||
# map the collections that turn up there onto the categories confluent asks
|
||||
# for
|
||||
_fwcategorybyurl = (
|
||||
('/Drives/', 'disks'),
|
||||
('/Storage/', 'disks'),
|
||||
('/PCIeDevices/', 'adapters'),
|
||||
('/NetworkAdapters/', 'adapters'),
|
||||
('/NetworkInterfaces/', 'adapters'),
|
||||
)
|
||||
|
||||
def _fwcategory(self, fwi):
|
||||
"""Which category a firmware inventory entry belongs to.
|
||||
|
||||
Returns None when the entry gives nothing to judge by.
|
||||
"""
|
||||
related = fwi.get('RelatedItem', [])
|
||||
for item in related:
|
||||
url = item.get('@odata.id', '')
|
||||
for frag, category in self._fwcategorybyurl:
|
||||
if frag in url:
|
||||
return category
|
||||
return 'core' if related else None
|
||||
|
||||
async def get_firmware(self, components=(), category=None):
|
||||
self._fwnamemap = {}
|
||||
oem = await self.oem()
|
||||
|
||||
@@ -655,43 +655,13 @@ class IpmiHandler:
|
||||
await self.ipmicmd.install_bmc_certificate(cert)
|
||||
|
||||
async def handle_alerts(self):
|
||||
if self.element[3] == 'destinations':
|
||||
if len(self.element) == 4:
|
||||
# A list of destinations
|
||||
maxdest = await self.ipmicmd.get_alert_destination_count()
|
||||
for alertidx in range(0, maxdest + 1):
|
||||
await self.output.put(msg.ChildCollection(alertidx))
|
||||
return
|
||||
elif len(self.element) == 5:
|
||||
alertidx = int(self.element[-1])
|
||||
if self.op == 'read':
|
||||
destdata = await self.ipmicmd.get_alert_destination(alertidx)
|
||||
await self.output.put(msg.AlertDestination(
|
||||
ip=destdata['address'],
|
||||
acknowledge=destdata['acknowledge_required'],
|
||||
acknowledge_timeout=destdata.get('acknowledge_timeout', None),
|
||||
retries=destdata['retries'],
|
||||
name=self.node))
|
||||
return
|
||||
elif self.op == 'update':
|
||||
alertparms = self.inputdata.alert_params_by_node(
|
||||
self.node)
|
||||
alertargs = {}
|
||||
if 'acknowledge' in alertparms:
|
||||
alertargs['acknowledge_required'] = alertparms['acknowledge']
|
||||
if 'acknowledge_timeout' in alertparms:
|
||||
alertargs['acknowledge_timeout'] = alertparms['acknowledge_timeout']
|
||||
if 'ip' in alertparms:
|
||||
alertargs['ip'] = alertparms['ip']
|
||||
if 'retries' in alertparms:
|
||||
alertargs['retries'] = alertparms['retries']
|
||||
await self.ipmicmd.set_alert_destination(destination=alertidx,
|
||||
**alertargs)
|
||||
return
|
||||
elif self.op == 'delete':
|
||||
await self.ipmicmd.clear_alert_destination(alertidx)
|
||||
return
|
||||
raise Exception('Not implemented')
|
||||
# Redfish describes where to send events with the EventService
|
||||
# subscription collection, which is a different model from the numbered
|
||||
# ipmi PET destinations this resource was built around, so say so rather
|
||||
# than calling methods the redfish client does not have
|
||||
raise pygexc.UnsupportedFunctionality(
|
||||
'Alert destinations are not implemented for redfish, use the '
|
||||
'EventService subscriptions on the bmc directly')
|
||||
|
||||
async def handle_nets(self):
|
||||
if len(self.element) == 3:
|
||||
@@ -1437,9 +1407,23 @@ class IpmiHandler:
|
||||
await self.ipmicmd.set_domain_name(dn)
|
||||
return
|
||||
|
||||
_locationfields = ('room', 'location', 'building', 'rack', 'contactnames')
|
||||
|
||||
async def handle_location_config(self):
|
||||
if 'read' == self.op:
|
||||
lc = await self.ipmicmd.get_location_information()
|
||||
await self.output.put(msg.KeyValueData(
|
||||
await self.ipmicmd.get_location_information(), self.node))
|
||||
return
|
||||
elif 'update' == self.op:
|
||||
attribs = self.inputdata.get_attributes(self.node)
|
||||
locargs = {x: attribs[x] for x in self._locationfields
|
||||
if x in attribs}
|
||||
if not locargs:
|
||||
raise exc.InvalidArgumentException(
|
||||
'Location accepts only: {0}'.format(
|
||||
', '.join(self._locationfields)))
|
||||
await self.ipmicmd.set_location_information(**locargs)
|
||||
return
|
||||
|
||||
async def handle_bmcconfig(self, advanced=False, extended=False):
|
||||
if 'read' == self.op:
|
||||
|
||||
Reference in New Issue
Block a user