示例#1
0
 def add_sdr(self, sdrbytes):
     newent = SDREntry(sdrbytes)
     if newent.sdrtype == TYPE_SENSOR:
         id = newent.sensor_number
         if id in self.sensors:
             raise exc.BmcErrorException("Duplicate sensor number " + id)
         self.sensors[id] = newent
     elif newent.sdrtype == TYPE_FRU:
         id = newent.fru_number
         if id in self.fru:
             raise exc.BmcErrorException("Duplicate FRU identifier " + id)
         self.fru[id] = newent
示例#2
0
 def get_sdr(self):
     rsp = self.ipmicmd.raw_command(netfn=0x0a, command=0x20)
     if (rsp['data'][0] != 0x51):
         # we only understand SDR version 51h, the only version defined
         # at time of this writing
         raise NotImplementedError
     #NOTE(jbjohnso): we actually don't need to care about 'numrecords'
     # since FFFF marks the end explicitly
     #numrecords = (rsp['data'][2] << 8) + rsp['data'][1]
     #NOTE(jbjohnso): don't care about 'free space' at the moment
     #NOTE(jbjohnso): most recent timstamp data for add and erase could be
     # handy to detect cache staleness, but for now will assume invariant
     # over life of session
     #NOTE(jbjohnso): not looking to support the various options in op
     # support, ignore those for now, reservation if some BMCs can't read
     # full SDR in one slurp
     recid = 0
     rsvid = 0  # partial 'get sdr' will require this
     offset = 0
     size = 0xff
     while recid != 0xffff:  # per 33.12 Get SDR command, 0xffff marks end
         rqdata = [rsvid & 0xff, rsvid >> 8,
                   recid & 0xff, recid >> 8,
                   offset, size]
         rsp = self.ipmicmd.raw_command(netfn=0x0a, command=0x23,
                                        data=rqdata)
         newrecid = (rsp['data'][1] << 8) + rsp['data'][0]
         self.add_sdr(rsp['data'][2:])
         if newrecid == recid:
             raise exc.BmcErrorException("Incorrect SDR record id from BMC")
         recid = newrecid
示例#3
0
 def _parse_chassis(self):
     offset = 8 * self.databytes[2]
     if offset == 0:
         return
     if self.databytes[offset] & 0b1111 != 1:
         raise iexc.BmcErrorException("Invallid/Unsupported chassis area")
     inf = self.info
     # ignore length field, just process the data
     inf['Chassis type'] = enclosure_types[self.databytes[offset + 2]]
     inf['Chassis part number'], offset = self._decode_tlv(offset + 3)
     inf['Chassis serial number'], offset = self._decode_tlv(offset)
     inf['chassis_extra'] = []
     self.extract_extra(inf['chassis_extra'], offset)
示例#4
0
 def _parse_board(self):
     offset = 8 * self.databytes[3]
     if offset == 0:
         return
     if self.databytes[offset] & 0b1111 != 1:
         raise iexc.BmcErrorException("Invalid/Unsupported board info area")
     inf = self.info
     language = self.databytes[offset + 2]
     inf['Board manufacture date'] = decode_fru_date(
         self.databytes[offset + 3:offset + 6])
     inf['Board manufacturer'], offset = self._decode_tlv(offset + 6)
     inf['Board product name'], offset = self._decode_tlv(offset, language)
     inf['Board serial number'], offset = self._decode_tlv(offset, language)
     inf['Board model'], offset = self._decode_tlv(offset, language)
     _, offset = self._decode_tlv(offset, language)  # decode but discard
     inf['board_extra'] = []
     self.extract_extra(inf['board_extra'], offset, language)
示例#5
0
 def get_sdr(self):
     repinfo = self.ipmicmd.xraw_command(netfn=0x0a, command=0x20)
     repinfo['data'] = bytearray(repinfo['data'])
     if (repinfo['data'][0] != 0x51):
         # we only understand SDR version 51h, the only version defined
         # at time of this writing
         raise NotImplementedError
     #NOTE(jbjohnso): we actually don't need to care about 'numrecords'
     # since FFFF marks the end explicitly
     #numrecords = (rsp['data'][2] << 8) + rsp['data'][1]
     #NOTE(jbjohnso): don't care about 'free space' at the moment
     #NOTE(jbjohnso): most recent timstamp data for add and erase could be
     # handy to detect cache staleness, but for now will assume invariant
     # over life of session
     #NOTE(jbjohnso): not looking to support the various options in op
     # support, ignore those for now, reservation if some BMCs can't read
     # full SDR in one slurp
     recid = 0
     rsvid = 0  # partial 'get sdr' will require this
     offset = 0
     size = 0xff
     chunksize = 128
     self.broken_sensor_ids = {}
     while recid != 0xffff:  # per 33.12 Get SDR command, 0xffff marks end
         newrecid = 0
         currlen = 0
         sdrdata = bytearray()
         while True:  # loop until SDR fetched wholly
             if size != 0xff and rsvid == 0:
                 rsvid = self.get_sdr_reservation()
             rqdata = [
                 rsvid & 0xff, rsvid >> 8, recid & 0xff, recid >> 8, offset,
                 size
             ]
             sdrrec = self.ipmicmd.raw_command(netfn=0x0a,
                                               command=0x23,
                                               data=rqdata)
             if sdrrec['code'] == 0xca:
                 if size == 0xff:  # get just 5 to get header to know length
                     size = 5
                 elif size > 5:
                     size /= 2
                     # push things over such that it's less
                     # likely to be just 1 short of a read
                     # and incur a whole new request
                     size += 2
                     chunksize = size
                 continue
             if sdrrec['code'] == 0xc5:  # need a new reservation id
                 rsvid = 0
                 continue
             if sdrrec['code'] != 0:
                 raise exc.IpmiException(sdrrec['error'])
             if newrecid == 0:
                 newrecid = (sdrrec['data'][1] << 8) + sdrrec['data'][0]
             if currlen == 0:
                 currlen = sdrrec['data'][6] + 5  # compensate for header
             sdrdata.extend(sdrrec['data'][2:])
             # determine next offset to use based on current offset and the
             # size used last time.
             offset += size
             if offset >= currlen:
                 break
             if size == 5 and offset == 5:
                 # bump up size after header retrieval
                 size = chunksize
             if (offset + size) > currlen:
                 size = currlen - offset
         self.add_sdr(sdrdata)
         offset = 0
         if size != 0xff:
             size = 5
         if newrecid == recid:
             raise exc.BmcErrorException("Incorrect SDR record id from BMC")
         recid = newrecid
     for sid in self.broken_sensor_ids:
         del self.sensors[sid]
示例#6
0
文件: sdr.py 项目: spyd3rweb/pyghmi
 def get_sdr(self):
     repinfo = self.ipmicmd.xraw_command(netfn=0x0a, command=0x20)
     repinfo['data'] = bytearray(repinfo['data'])
     if (repinfo['data'][0] != 0x51):
         # we only understand SDR version 51h, the only version defined
         # at time of this writing
         raise NotImplementedError
     # NOTE(jbjohnso): we actually don't need to care about 'numrecords'
     # since FFFF marks the end explicitly
     # numrecords = (rsp['data'][2] << 8) + rsp['data'][1]
     # NOTE(jbjohnso): don't care about 'free space' at the moment
     # NOTE(jbjohnso): most recent timstamp data for add and erase could be
     # handy to detect cache staleness, but for now will assume invariant
     # over life of session
     # NOTE(jbjohnso): not looking to support the various options in op
     # support, ignore those for now, reservation if some BMCs can't read
     # full SDR in one slurp
     modtime = struct.unpack('!Q', repinfo['data'][5:13])[0]
     recid = 0
     rsvid = 0  # partial 'get sdr' will require this
     offset = 0
     size = 0xff
     chunksize = 128
     try:
         csdrs = shared_sdrs[
             (self.fw_major, self.fw_minor, self.mfg_id, self.prod_id,
              self.device_id, modtime)]
         self.sensors = csdrs['sensors']
         self.fru = csdrs['fru']
         return
     except KeyError:
         pass
     cachefilename = None
     self.broken_sensor_ids = {}
     if self.cachedir:
         cachefilename = 'sdrcache.{0}.{1}.{2}.{3}.{4}.{5}'.format(
             self.mfg_id, self.prod_id, self.device_id, self.fw_major,
             self.fw_minor, modtime)
         cachefilename = os.path.join(self.cachedir, cachefilename)
     if cachefilename and os.path.isfile(cachefilename):
         with open(cachefilename, 'r') as cfile:
             csdrs = pickle.load(cfile)
             for sdrdata in csdrs:
                 self.add_sdr(sdrdata)
             for sid in self.broken_sensor_ids:
                 try:
                     del self.sensors[sid]
                 except KeyError:
                     pass
             shared_sdrs[
                 (self.fw_major, self.fw_minor, self.mfg_id, self.prod_id,
                  self.device_id, modtime)] = {
                 'sensors': self.sensors,
                 'fru': self.fru,
             }
             return
     sdrraw = [] if cachefilename else None
     while recid != 0xffff:  # per 33.12 Get SDR command, 0xffff marks end
         newrecid = 0
         currlen = 0
         sdrdata = bytearray()
         while True:  # loop until SDR fetched wholly
             if size != 0xff and rsvid == 0:
                 rsvid = self.get_sdr_reservation()
             rqdata = [rsvid & 0xff, rsvid >> 8,
                       recid & 0xff, recid >> 8,
                       offset, size]
             sdrrec = self.ipmicmd.raw_command(netfn=0x0a, command=0x23,
                                               data=rqdata)
             if sdrrec['code'] == 0xca:
                 if size == 0xff:  # get just 5 to get header to know length
                     size = 5
                 elif size > 5:
                     size /= 2
                     # push things over such that it's less
                     # likely to be just 1 short of a read
                     # and incur a whole new request
                     size += 2
                     chunksize = size
                 continue
             if sdrrec['code'] == 0xc5:  # need a new reservation id
                 rsvid = 0
                 continue
             if sdrrec['code'] != 0:
                 raise exc.IpmiException(sdrrec['error'])
             if newrecid == 0:
                 newrecid = (sdrrec['data'][1] << 8) + sdrrec['data'][0]
             if currlen == 0:
                 currlen = sdrrec['data'][6] + 5  # compensate for header
             sdrdata.extend(sdrrec['data'][2:])
             # determine next offset to use based on current offset and the
             # size used last time.
             offset += size
             if offset >= currlen:
                 break
             if size == 5 and offset == 5:
                 # bump up size after header retrieval
                 size = chunksize
             if (offset + size) > currlen:
                 size = currlen - offset
         self.add_sdr(sdrdata)
         if sdrraw is not None:
             sdrraw.append(sdrdata)
         offset = 0
         if size != 0xff:
             size = 5
         if newrecid == recid:
             raise exc.BmcErrorException("Incorrect SDR record id from BMC")
         recid = newrecid
     for sid in self.broken_sensor_ids:
         try:
             del self.sensors[sid]
         except KeyError:
             pass
     shared_sdrs[(self.fw_major, self.fw_minor, self.mfg_id, self.prod_id,
                  self.device_id, modtime)] = {
         'sensors': self.sensors,
         'fru': self.fru,
     }
     if cachefilename:
         suffix = ''.join(
             random.choice(string.ascii_lowercase) for _ in range(12))
         with open(cachefilename + '.' + suffix, 'w') as cfile:
             pickle.dump(sdrraw, cfile)
         os.rename(cachefilename + '.' + suffix, cachefilename)