pyghmi 1.5.59__tar.gz → 1.5.61__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. {pyghmi-1.5.59 → pyghmi-1.5.61}/ChangeLog +14 -0
  2. {pyghmi-1.5.59 → pyghmi-1.5.61}/PKG-INFO +1 -1
  3. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/energy.py +20 -1
  4. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/handler.py +23 -22
  5. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/imm.py +41 -35
  6. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/nextscale.py +7 -2
  7. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/lenovo/xcc.py +27 -7
  8. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/PKG-INFO +1 -1
  9. pyghmi-1.5.61/pyghmi.egg-info/pbr.json +1 -0
  10. pyghmi-1.5.59/pyghmi.egg-info/pbr.json +0 -1
  11. {pyghmi-1.5.59 → pyghmi-1.5.61}/.coveragerc +0 -0
  12. {pyghmi-1.5.59 → pyghmi-1.5.61}/.stestr.conf +0 -0
  13. {pyghmi-1.5.59 → pyghmi-1.5.61}/AUTHORS +0 -0
  14. {pyghmi-1.5.59 → pyghmi-1.5.61}/CONTRIBUTING.rst +0 -0
  15. {pyghmi-1.5.59 → pyghmi-1.5.61}/LICENSE +0 -0
  16. {pyghmi-1.5.59 → pyghmi-1.5.61}/MANIFEST.in +0 -0
  17. {pyghmi-1.5.59 → pyghmi-1.5.61}/README +0 -0
  18. {pyghmi-1.5.59 → pyghmi-1.5.61}/README.md +0 -0
  19. {pyghmi-1.5.59 → pyghmi-1.5.61}/builddeb +0 -0
  20. {pyghmi-1.5.59 → pyghmi-1.5.61}/buildrpm +0 -0
  21. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/requirements.txt +0 -0
  22. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/source/conf.py +0 -0
  23. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/source/contributor/index.rst +0 -0
  24. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/source/index.rst +0 -0
  25. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/source/install/index.rst +0 -0
  26. {pyghmi-1.5.59 → pyghmi-1.5.61}/doc/source/reference/index.rst +0 -0
  27. {pyghmi-1.5.59 → pyghmi-1.5.61}/makesetup +0 -0
  28. {pyghmi-1.5.59 → pyghmi-1.5.61}/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/post.yaml +0 -0
  29. {pyghmi-1.5.59 → pyghmi-1.5.61}/playbooks/legacy/tempest-devstack-ironic-pxe_ipmitool-pyghmi-src/run.yaml +0 -0
  30. {pyghmi-1.5.59 → pyghmi-1.5.61}/py27-constraints.txt +0 -0
  31. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/__init__.py +0 -0
  32. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/cmd/__init__.py +0 -0
  33. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/cmd/fakebmc.py +0 -0
  34. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/cmd/pyghmicons.py +0 -0
  35. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/cmd/pyghmiutil.py +0 -0
  36. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/cmd/virshbmc.py +0 -0
  37. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/constants.py +0 -0
  38. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/exceptions.py +0 -0
  39. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/__init__.py +0 -0
  40. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/bmc.py +0 -0
  41. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/command.py +0 -0
  42. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/console.py +0 -0
  43. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/events.py +0 -0
  44. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/fru.py +0 -0
  45. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/__init__.py +0 -0
  46. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/generic.py +0 -0
  47. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/__init__.py +0 -0
  48. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/config.py +0 -0
  49. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/cpu.py +0 -0
  50. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/dimm.py +0 -0
  51. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/drive.py +0 -0
  52. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/firmware.py +0 -0
  53. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/inventory.py +0 -0
  54. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/pci.py +0 -0
  55. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/psu.py +0 -0
  56. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/raid_controller.py +0 -0
  57. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lenovo/raid_drive.py +0 -0
  58. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/oem/lookup.py +0 -0
  59. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/__init__.py +0 -0
  60. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/constants.py +0 -0
  61. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/localsession.py +0 -0
  62. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/serversession.py +0 -0
  63. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/session.py +0 -0
  64. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/simplesession.py +0 -0
  65. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/spd.py +0 -0
  66. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/private/util.py +0 -0
  67. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/ipmi/sdr.py +0 -0
  68. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/media.py +0 -0
  69. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/__init__.py +0 -0
  70. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/command.py +0 -0
  71. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/__init__.py +0 -0
  72. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/dell/__init__.py +0 -0
  73. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/dell/idrac.py +0 -0
  74. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/dell/main.py +0 -0
  75. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/generic.py +0 -0
  76. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/lenovo/__init__.py +0 -0
  77. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/lenovo/main.py +0 -0
  78. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/lenovo/tsma.py +0 -0
  79. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/redfish/oem/lookup.py +0 -0
  80. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/storage.py +0 -0
  81. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/tests/__init__.py +0 -0
  82. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/tests/unit/__init__.py +0 -0
  83. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/tests/unit/base.py +0 -0
  84. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/tests/unit/ipmi/__init__.py +0 -0
  85. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/tests/unit/ipmi/test_sdr.py +0 -0
  86. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/util/__init__.py +0 -0
  87. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/util/parse.py +0 -0
  88. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/util/webclient.py +0 -0
  89. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi/version.py +0 -0
  90. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/SOURCES.txt +0 -0
  91. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/dependency_links.txt +0 -0
  92. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/entry_points.txt +0 -0
  93. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/not-zip-safe +0 -0
  94. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/requires.txt +0 -0
  95. {pyghmi-1.5.59 → pyghmi-1.5.61}/pyghmi.egg-info/top_level.txt +0 -0
  96. {pyghmi-1.5.59 → pyghmi-1.5.61}/python-pyghmi.spec +0 -0
  97. {pyghmi-1.5.59 → pyghmi-1.5.61}/python-pyghmi.spec.tmpl +0 -0
  98. {pyghmi-1.5.59 → pyghmi-1.5.61}/requirements.txt +0 -0
  99. {pyghmi-1.5.59 → pyghmi-1.5.61}/setup.cfg +0 -0
  100. {pyghmi-1.5.59 → pyghmi-1.5.61}/setup.py +0 -0
  101. {pyghmi-1.5.59 → pyghmi-1.5.61}/setup.py.tmpl +0 -0
  102. {pyghmi-1.5.59 → pyghmi-1.5.61}/test-requirements.txt +0 -0
  103. {pyghmi-1.5.59 → pyghmi-1.5.61}/tox.ini +0 -0
  104. {pyghmi-1.5.59 → pyghmi-1.5.61}/wheezy.patch +0 -0
  105. {pyghmi-1.5.59 → pyghmi-1.5.61}/zuul.d/project.yaml +0 -0
@@ -1,6 +1,20 @@
1
1
  CHANGES
2
2
  =======
3
3
 
4
+ 1.5.61
5
+ ------
6
+
7
+ * Follow state of validate job when updating firmware
8
+ * Handle FRU with blank mac area
9
+ * Stage alternate power meter support
10
+
11
+ 1.5.60
12
+ ------
13
+
14
+ * Avoid doing extra AddNewVolWithNaAsync calls
15
+ * Update storage code to handle 2023 XCC FW
16
+ * Fix for newer SMMv2 firmware
17
+
4
18
  1.5.59
5
19
  ------
6
20
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: pyghmi
3
- Version: 1.5.59
3
+ Version: 1.5.61
4
4
  Summary: Python General Hardware Management Initiative (IPMI and others)
5
5
  Home-page: http://github.com/openstack/pyghmi/
6
6
  Author: Jarrod Johnson
@@ -31,7 +31,9 @@ class EnergyManager(object):
31
31
  try:
32
32
  rsp = ipmicmd.xraw_command(netfn=0x3a, command=0x32, data=[4, 2, 0, 0, 0])
33
33
  if len(rsp['data']) >= 8:
34
- self.supportedmeters = ('DC Energy',)
34
+ self.supportedmeters = ('DC Energy',) # 'GPU Power',
35
+ # 'Node Power', 'Total Power')
36
+ self._mypowermeters = ('node power', 'total power', 'gpu power', 'riser 1 power', 'riser 2 power')
35
37
  self._usefapm = True
36
38
  return
37
39
  except pygexc.IpmiException:
@@ -57,6 +59,23 @@ class EnergyManager(object):
57
59
  else:
58
60
  self.supportedmeters = ('DC Energy',)
59
61
 
62
+ def supports(self, name):
63
+ if name.lower() in self._mypowermeters:
64
+ return True
65
+ return False
66
+
67
+ def get_sensor(self, name, ipmicmd):
68
+ if name.lower() not in self._mypowermeters:
69
+ raise pygexc.UnsupportedFunctionality('Unrecogcized sensor')
70
+ rsp = ipmicmd.xraw_command(netfn=0x3a, command=0x32, data=[4, 8, 0, 0, 0])
71
+ npow, gpupow, r1pow, r2pow = struct.unpack('<HHHH', rsp['data'][6:10])
72
+ if name.lower().startswith('node'):
73
+ return npow, 'W'
74
+ elif name.lower().startswith('gpu'):
75
+ return gpupow, 'W'
76
+ elif name.lower().startswith('total'):
77
+ return npow + gpupow, 'W'
78
+
60
79
  def get_fapm_energy(self, ipmicmd):
61
80
  rsp = ipmicmd.xraw_command(netfn=0x3a, command=0x32, data=[4, 2, 0, 0, 0])
62
81
  j, mj = struct.unpack('<IH', rsp['data'][2:8])
@@ -718,27 +718,28 @@ class OEMHandler(generic.OEMHandler):
718
718
  fru['FRU Number'] = bextra[0]
719
719
  fru['Revision'] = bextra[4]
720
720
  macs = bextra[6]
721
- macprefix = None
722
- idx = 0
723
- endidx = len(macs) - 5
724
- macprefix = None
725
- while idx < endidx:
726
- currmac = macs[idx:idx + 6]
727
- if not isinstance(currmac, bytearray):
728
- # invalid vpd format, abort attempts to extract
729
- # mac in this way
730
- break
731
- if currmac == b'\x00\x00\x00\x00\x00\x00':
732
- break
733
- # VPD may veer off, detect and break off
734
- if macprefix is None:
735
- macprefix = currmac[:3]
736
- elif currmac[:3] != macprefix:
737
- break
738
- ms = mac_format.format(*currmac)
739
- ifidx = idx / 6 + 1
740
- fru['MAC Address {0}'.format(ifidx)] = ms
741
- idx = idx + 6
721
+ if macs:
722
+ macprefix = None
723
+ idx = 0
724
+ endidx = len(macs) - 5
725
+ macprefix = None
726
+ while idx < endidx:
727
+ currmac = macs[idx:idx + 6]
728
+ if not isinstance(currmac, bytearray):
729
+ # invalid vpd format, abort attempts to extract
730
+ # mac in this way
731
+ break
732
+ if currmac == b'\x00\x00\x00\x00\x00\x00':
733
+ break
734
+ # VPD may veer off, detect and break off
735
+ if macprefix is None:
736
+ macprefix = currmac[:3]
737
+ elif currmac[:3] != macprefix:
738
+ break
739
+ ms = mac_format.format(*currmac)
740
+ ifidx = idx / 6 + 1
741
+ fru['MAC Address {0}'.format(ifidx)] = ms
742
+ idx = idx + 6
742
743
  except (AttributeError, KeyError, IndexError):
743
744
  pass
744
745
  if self.has_xcc and name and name.startswith('PSU '):
@@ -1202,7 +1203,7 @@ class OEMHandler(generic.OEMHandler):
1202
1203
  if self.has_xcc:
1203
1204
  return self.immhandler.get_bmc_configuration()
1204
1205
  if self.is_fpc:
1205
- return self.smmhandler.get_bmc_configuration()
1206
+ return self.smmhandler.get_bmc_configuration(self._fpc_variant)
1206
1207
  if self.has_tsma:
1207
1208
  return self.tsmahandler.get_bmc_configuration()
1208
1209
  return super(OEMHandler, self).get_bmc_configuration()
@@ -684,8 +684,13 @@ class IMMClient(object):
684
684
  return ()
685
685
 
686
686
  def get_oem_sensor_descriptions(self, ipmicmd):
687
- return [{'name': x, 'type': 'Energy'
688
- } for x in self.get_oem_sensor_names(ipmicmd)]
687
+ desc = []
688
+ for x in self.get_oem_sensor_names(ipmicmd):
689
+ desc.append({
690
+ 'name': x,
691
+ 'type': 'Power' if 'Power' in x else 'Energy'
692
+ })
693
+ return desc
689
694
 
690
695
  def get_oem_sensor_reading(self, name, ipmicmd):
691
696
  if self._energymanager is None:
@@ -694,8 +699,15 @@ class IMMClient(object):
694
699
  kwh = self._energymanager.get_ac_energy(ipmicmd)
695
700
  elif name == 'DC Energy':
696
701
  kwh = self._energymanager.get_dc_energy(ipmicmd)
702
+ elif self._energymanager.supports(name):
703
+ value, units = self._energymanager.get_sensor(name, ipmicmd)
704
+ return sdr.SensorReading({
705
+ 'name': name, 'imprecision': None,
706
+ 'value': value,
707
+ 'states': [], 'state_ids': [], 'health': pygconst.Health.Ok,
708
+ 'type': 'Power'}, units)
697
709
  else:
698
- raise pygexc.UnsupportedFunctionality('No sunch sensor ' + name)
710
+ raise pygexc.UnsupportedFunctionality('No such sensor ' + name)
699
711
  return sdr.SensorReading({'name': name, 'imprecision': None,
700
712
  'value': kwh, 'states': [],
701
713
  'state_ids': [],
@@ -1489,12 +1501,23 @@ class XCCClient(IMMClient):
1489
1501
  def _create_array(self, pool):
1490
1502
  params = self._parse_array_spec(pool)
1491
1503
  cid = params['controller'].split(',')[0]
1504
+ cslotno = params['controller'].split(',')[1]
1492
1505
  url = '/api/function/raid_conf?params=raidlink_GetDefaultVolProp'
1493
1506
  args = (url, cid, 0, params['drives'])
1494
1507
  props = self.wc.grab_json_response(','.join([str(x) for x in args]))
1508
+ usesctrlslot = False
1495
1509
  if not props: # newer firmware requires raidlevel too
1496
1510
  args = (url, cid, params['raidlevel'], 0, params['drives'])
1497
1511
  props = self.wc.grab_json_response(','.join([str(x) for x in args]))
1512
+ elif 'return' in props and props['return'] == 22:
1513
+ # Jan 2023 XCC FW - without controller slot number
1514
+ args = (url, cid, params['raidlevel'], 0, params['drives'])
1515
+ props = self.wc.grab_json_response(','.join([str(x) for x in args]))
1516
+ if 'return' in props and props['return'] == 22:
1517
+ usesctrlslot = True
1518
+ # Jan 2023 XCC FW - with controller slot number
1519
+ args = (url, cid, params['raidlevel'], 0, params['drives'], cslotno)
1520
+ props = self.wc.grab_json_response(','.join([str(x) for x in args]))
1498
1521
  props = props['items'][0]
1499
1522
  volumes = pool.volumes
1500
1523
  remainingcap = params['capacity']
@@ -1565,14 +1588,14 @@ class XCCClient(IMMClient):
1565
1588
  parms = {'raidlink_AddNewVolWithNaAsync': arglist}
1566
1589
  rsp = self.wc.grab_json_response(url, parms)
1567
1590
  if rsp['return'] == 14: # newer firmware
1568
- if 'supported_cpwb' in props: # Whitley
1591
+ if 'supported_cpwb' in props and not usesctrlslot: # no ctrl_type
1569
1592
  arglist = '{0},{1},{2},{3},{4},{5},{6},'.format(
1570
1593
  cnum, params['raidlevel'], params['spans'],
1571
1594
  params['perspan'], 0, params['drives'], params['hotspares'])
1572
1595
  arglist += ''.join(vols)
1573
1596
  parms = {'raidlink_AddNewVolWithNaAsync': arglist}
1574
1597
  rsp = self.wc.grab_json_response(url, parms)
1575
- else: # Purley
1598
+ else: # with ctrl_type
1576
1599
  if cid[2] == 2:
1577
1600
  cnum = cid[1]
1578
1601
  arglist = '{0},{1},{2},{3},{4},{5},'.format(
@@ -1615,32 +1638,6 @@ class XCCClient(IMMClient):
1615
1638
  # oemsensornames = oemsensornames + (name,)
1616
1639
  # return oemsensornames
1617
1640
 
1618
- def get_oem_sensor_descriptions(self, ipmicmd):
1619
- oemdesc = [{'name': x, 'type': 'Energy'} for x in super(
1620
- XCCClient, self).get_oem_sensor_names(ipmicmd)]
1621
- return oemdesc
1622
- # therminfo = self.grab_cacheable_json(
1623
- # '/api/dataset/pwrmgmt?params=GetThermalRealTimeData', 1)
1624
- # if therminfo:
1625
- # for name in sorted(therminfo['items'][0]):
1626
- # if 'DIMM' in name and 'Temp' in name:
1627
- # oemdesc.append({'name': name, 'type': 'Temperature'})
1628
- # return oemdesc
1629
-
1630
- def get_oem_sensor_reading(self, name, ipmicmd):
1631
- if 'Energy' in name:
1632
- return super(XCCClient, self).get_oem_sensor_reading(name, ipmicmd)
1633
- therminfo = self.grab_cacheable_json(
1634
- '/api/dataset/pwrmgmt?params=GetThermalRealTimeData', 1)
1635
- temp = therminfo.get('items', [{}])[0].get(name, None)
1636
- if temp is None:
1637
- raise pygexc.UnsupportedFunctionality('No sunch sensor ' + name)
1638
- return sdr.SensorReading({'name': name, 'imprecision': None,
1639
- 'value': temp, 'states': [],
1640
- 'state_ids': [],
1641
- 'health': pygconst.Health.Ok,
1642
- 'type': 'Temperature'}, '°C')
1643
-
1644
1641
  def get_storage_configuration(self, logout=True):
1645
1642
  rsp = self.wc.grab_json_response(
1646
1643
  '/api/function/raid_alldevices?params=storage_GetAllDevices,0')
@@ -2021,8 +2018,10 @@ class XCCClient(IMMClient):
2021
2018
  raise Exception(uploadthread.rsp)
2022
2019
  raise Exception(errmsg)
2023
2020
  rsp = json.loads(uploadthread.rsp)
2024
- monitorurl = rsp['TaskMonitor']
2021
+ monitorurl = rsp['@odata.id']
2025
2022
  complete = False
2023
+ phase = "apply"
2024
+ statetype = 'TaskState'
2026
2025
  while not complete:
2027
2026
  pgress, status = self.grab_redfish_response_with_status(
2028
2027
  monitorurl)
@@ -2033,14 +2032,21 @@ class XCCClient(IMMClient):
2033
2032
  for msg in pgress.get('Messages', []):
2034
2033
  if 'Verify failed' in msg.get('Message', ''):
2035
2034
  raise Exception(msg['Message'])
2036
- state = pgress['TaskState']
2035
+ state = pgress[statetype]
2037
2036
  if state in ('Cancelled', 'Exception',
2038
2037
  'Interrupted', 'Suspended'):
2039
2038
  raise Exception(json.dumps(pgress['Messages']))
2040
2039
  pct = float(pgress['PercentComplete'])
2041
2040
  complete = state == 'Completed'
2042
- progress({'phase': 'apply', 'progress': pct})
2043
- if not complete:
2041
+ progress({'phase': phase, 'progress': pct})
2042
+ if complete:
2043
+ if 'OperationTransitionedToJob' in pgress['Messages'][0]['MessageId']:
2044
+ monitorurl = pgress['Messages'][0]['MessageArgs'][0]
2045
+ phase = 'validating'
2046
+ statetype = 'JobState'
2047
+ complete = False
2048
+ ipmisession.Session.pause(3)
2049
+ else:
2044
2050
  ipmisession.Session.pause(3)
2045
2051
  if bank == 'backup':
2046
2052
  return 'complete'
@@ -415,7 +415,7 @@ class SMMClient(object):
415
415
  5: 'Boosted',
416
416
  }
417
417
 
418
- def get_bmc_configuration(self):
418
+ def get_bmc_configuration(self, variant):
419
419
  settings = {}
420
420
  wc = self.wc
421
421
  wc.request(
@@ -453,7 +453,10 @@ class SMMClient(object):
453
453
  powercfg = self.ipmicmd.xraw_command(0x32, 0xa2)
454
454
  powercfg = bytearray(powercfg['data'])
455
455
  if len(powercfg) == 5:
456
- powercfg = powercfg[1:]
456
+ if variant and variant >> 5:
457
+ powercfg = powercfg[-2:]
458
+ else:
459
+ powercfg = powercfg[1:]
457
460
  val = powercfg[0]
458
461
  if val == 2:
459
462
  val = 'N+N'
@@ -700,6 +703,8 @@ class SMMClient(object):
700
703
  if None in powercfg:
701
704
  currcfg = self.ipmicmd.xraw_command(0x32, 0xa2)
702
705
  currcfg = bytearray(currcfg['data'])
706
+ if variant and variant >> 5 and len(currcfg) == 5:
707
+ currcfg = currcfg[-2:]
703
708
  if powercfg[0] is None:
704
709
  powercfg[0] = currcfg[0]
705
710
  if powercfg[1] is None:
@@ -811,12 +811,23 @@ class OEMHandler(generic.OEMHandler):
811
811
  def _create_array(self, pool):
812
812
  params = self._parse_array_spec(pool)
813
813
  cid = params['controller'].split(',')[0]
814
+ cslotno = params['controller'].split(',')[1]
814
815
  url = '/api/function/raid_conf?params=raidlink_GetDefaultVolProp'
815
816
  args = (url, cid, 0, params['drives'])
816
817
  props = self.wc.grab_json_response(','.join([str(x) for x in args]))
817
- if not props: # newer firmwarerequires raidlevel too
818
+ usesctrlslot = False
819
+ if not props: # newer firmware requires raidlevel too
818
820
  args = (url, cid, params['raidlevel'], 0, params['drives'])
819
821
  props = self.wc.grab_json_response(','.join([str(x) for x in args]))
822
+ elif 'return' in props and props['return'] == 22:
823
+ # Jan 2023 XCC FW - without controller slot number
824
+ args = (url, cid, params['raidlevel'], 0, params['drives'])
825
+ props = self.wc.grab_json_response(','.join([str(x) for x in args]))
826
+ if 'return' in props and props['return'] == 22:
827
+ usesctrlslot = True
828
+ # Jan 2023 XCC FW - with controller slot number
829
+ args = (url, cid, params['raidlevel'], 0, params['drives'], cslotno)
830
+ props = self.wc.grab_json_response(','.join([str(x) for x in args]))
820
831
  props = props['items'][0]
821
832
  volumes = pool.volumes
822
833
  remainingcap = params['capacity']
@@ -888,14 +899,14 @@ class OEMHandler(generic.OEMHandler):
888
899
  parms = {'raidlink_AddNewVolWithNaAsync': arglist}
889
900
  rsp = self.wc.grab_json_response(url, parms)
890
901
  if rsp['return'] == 14: # newer firmware
891
- if 'supported_cpwb' in props: # Whitley
902
+ if 'supported_cpwb' in props and not usesctrlslot: # no ctrl_type
892
903
  arglist = '{0},{1},{2},{3},{4},{5},{6},'.format(
893
904
  cnum, params['raidlevel'], params['spans'],
894
905
  params['perspan'], 0, params['drives'], params['hotspares'])
895
906
  arglist += ''.join(vols)
896
907
  parms = {'raidlink_AddNewVolWithNaAsync': arglist}
897
908
  rsp = self.wc.grab_json_response(url, parms)
898
- else: # Purley
909
+ else: # with ctrl_type
899
910
  if cid[2] == 2:
900
911
  cnum = cid[1]
901
912
  arglist = '{0},{1},{2},{3},{4},{5},'.format(
@@ -1145,8 +1156,10 @@ class OEMHandler(generic.OEMHandler):
1145
1156
  raise Exception(uploadthread.rsp)
1146
1157
  raise Exception(errmsg)
1147
1158
  rsp = json.loads(uploadthread.rsp)
1148
- monitorurl = rsp['TaskMonitor']
1159
+ monitorurl = rsp['@odata.id']
1149
1160
  complete = False
1161
+ phase = "apply"
1162
+ statetype = 'TaskState'
1150
1163
  while not complete:
1151
1164
  pgress = self._do_web_request(monitorurl, cache=False)
1152
1165
  if not pgress:
@@ -1154,15 +1167,22 @@ class OEMHandler(generic.OEMHandler):
1154
1167
  for msg in pgress.get('Messages', []):
1155
1168
  if 'Verify failed' in msg.get('Message', ''):
1156
1169
  raise Exception(msg['Message'])
1157
- state = pgress['TaskState']
1170
+ state = pgress[statetype]
1158
1171
  if state in ('Cancelled', 'Exception', 'Interrupted',
1159
1172
  'Suspended'):
1160
1173
  raise Exception(
1161
1174
  json.dumps(json.dumps(pgress['Messages'])))
1162
1175
  pct = float(pgress['PercentComplete'])
1163
1176
  complete = state == 'Completed'
1164
- progress({'phase': 'apply', 'progress': pct})
1165
- if not complete:
1177
+ progress({'phase': phase, 'progress': pct})
1178
+ if complete:
1179
+ if 'OperationTransitionedToJob' in pgress['Messages'][0]['MessageId']:
1180
+ monitorurl = pgress['Messages'][0]['MessageArgs'][0]
1181
+ phase = 'validating'
1182
+ statetype = 'JobState'
1183
+ complete = False
1184
+ time.sleep(3)
1185
+ else:
1166
1186
  time.sleep(3)
1167
1187
  if bank == 'backup':
1168
1188
  return 'complete'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: pyghmi
3
- Version: 1.5.59
3
+ Version: 1.5.61
4
4
  Summary: Python General Hardware Management Initiative (IPMI and others)
5
5
  Home-page: http://github.com/openstack/pyghmi/
6
6
  Author: Jarrod Johnson
@@ -0,0 +1 @@
1
+ {"git_version": "537fccb", "is_release": true}
@@ -1 +0,0 @@
1
- {"git_version": "bb46b94", "is_release": true}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes