def send_and_receive(self, msg): """Sends an IPMI request message and waits for its response. `msg` is a IPMI Message containing both the request and response. """ log().debug('IPMI Request [%s]', msg) retries = 0 while retries < self.max_retries: try: rx_data = self._send_and_receive_raw(msg.target, msg.lun, msg.netfn, chr(msg.cmdid) + encode_message(msg)) break except TimeoutError: pass retries += 1 else: raise TimeoutError() msg = create_message(msg.cmdid, msg.netfn + 1) decode_message(msg, rx_data[5:-1]) log().debug('IPMI Response [%s])', msg) return msg
def _receive_raw(self, rs_sa, rs_lun, rq_lun, rq_seq, netfn, cmd_id): start_time = time.time() rsp_received = False poll_returned_no_data = False while not rsp_received: timeout = self.timeout - (time.time() - start_time) if timeout <= 0 or poll_returned_no_data: raise TimeoutError() ret = self._dev.poll(int(timeout * 1000)) if ret == pyaardvark.POLL_NO_DATA: poll_returned_no_data = True continue (i2c_addr, rx_data) = self._dev.i2c_slave_read() log().debug('I2C RX from %02Xh [%s]', i2c_addr, ' '.join(['%02x' % ord(c) for c in rx_data])) rx_data = array.array('B', rx_data) rq_sa = i2c_addr << 1 rsp_received = self._rx_filter(rq_sa, rq_lun, rq_seq, rs_sa, rs_lun, netfn, cmd_id, rx_data) return rx_data
def _send_and_receive_raw(self, target, rs_lun, netfn, raw_bytes): if hasattr(target, 'routing') and len(target.routing) > 1: raise RuntimeError('Bridging is not supported yet') rq_seq = self.next_sequence_number self._inc_sequence_number() rs_sa = target.ipmb_address cmd_id = ord(raw_bytes[0]) retries = 0 while retries < self.max_retries: try: self._send_raw(rs_sa, rs_lun, rq_seq, netfn, raw_bytes) rx_data = self._receive_raw(rs_sa, rs_lun, 0, rq_seq, netfn, cmd_id) break except TimeoutError: log().warning('I2C transaction timed out'), pass retries += 1 else: raise TimeoutError() return rx_data.tostring()
def _send_and_receive(self, target, lun, netfn, cmdid, payload): self._inc_sequence_number() # assemble IPMB header header = IpmbHeader() header.netfn = netfn header.rs_lun = lun header.rs_sa = target.ipmb_address header.rq_seq = self.next_sequence_number header.rq_lun = 0 header.rq_sa = self.slave_address header.cmd_id = cmdid retries = 0 while retries < self.max_retries: try: self._send_raw(header, payload) rx_data = self._receive_raw(header) break except TimeoutError: log().warning('I2C transaction timed out'), pass retries += 1 else: raise TimeoutError() return rx_data.tostring()[5:-1]
def rmcp_ping(self): if self._interface_type == 'serial-terminal': raise RuntimeError( 'rcmp_ping not supported on "serial-terminal" interface') # for now this uses impitool.. cmd = self.IPMITOOL_PATH cmd += (' -I %s' % self._interface_type) cmd += (' -H %s' % self._session._rmcp_host) cmd += (' -p %s' % self._session._rmcp_port) if self._session.auth_type == Session.AUTH_TYPE_NONE: cmd += (' -A NONE') elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD: cmd += (' -U "%s"' % self._session._auth_username) cmd += (' -P "%s"' % self._session._auth_password) cmd += (' session info all') log().debug('Running ipmitool "%s"', cmd) child = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE) child.communicate() log().debug('rc = %s' % child.returncode) if child.returncode: raise TimeoutError()
def _receive_raw(self, header): start_time = time.time() rsp_received = False poll_returned_no_data = False while not rsp_received: timeout = self.timeout - (time.time() - start_time) if timeout <= 0 or poll_returned_no_data: raise TimeoutError() ret = self._dev.poll(int(timeout * 1000)) # poll returns an empty list if no event is pending if not ret: poll_returned_no_data = True continue (i2c_addr, rx_data) = self._dev.i2c_slave_read() log().debug('I2C RX from %02Xh [%s]', i2c_addr << 1, ' '.join(['%02x' % ord(c) for c in rx_data])) rx_data = array.array('B', rx_data) rq_sa = array.array('B', [i2c_addr << 1,]) rsp_received = self._rx_filter(header, rq_sa + rx_data) return rx_data
def _send_raw(self, header, raw_bytes): cmd_data = [ord(c) for c in raw_bytes] tx_data = self._encode_ipmb_msg_req(header, cmd_data) i2c_addr = header.rs_sa >> 1 self._dev.i2c_master_write(i2c_addr, tx_data.tostring()) log().debug('I2C TX to %02Xh [%s]', i2c_addr, ' '.join(['%02x' % b for b in tx_data]))
def _send_raw(self, rs_sa, rs_lun, rq_seq, netfn, raw_bytes): rq_sa = self.slave_address cmd_id = ord(raw_bytes[0]) cmd_data = [ord(c) for c in raw_bytes[1:]] tx_data = self._encode_ipmb_msg_req(rs_sa, rs_lun, netfn, rq_sa, 0, rq_seq, cmd_id, cmd_data) i2c_addr = rs_sa >> 1 self._dev.i2c_master_write(i2c_addr, tx_data.tostring()) log().debug('I2C TX to %02Xh [%s]', i2c_addr, ' '.join(['%02x' % b for b in tx_data]))
def _run_ipmitool(self, cmd): """Legacy call of ipmitool (will be removed in future). """ log().debug('Running ipmitool "%s"', cmd) child = Popen(cmd, shell=True, stdout=PIPE) output = child.communicate()[0] log().debug('return with rc=%d, output was:\n%s', child.returncode, output) return output, child.returncode
def send_and_receive(self, req): log().debug('IPMI Request [%s]', req) req_data = (chr(req.cmdid)) req_data += encode_message(req) rsp_data = self.send_and_receive_raw(req.target, req.lun, req.netfn, req_data) rsp = create_message(req.cmdid, req.netfn + 1) decode_message(rsp, rsp_data.tostring()) log().debug('IPMI Response [%s])', rsp) return rsp
def _send_and_receive_raw(self, target, lun, netfn, raw_bytes): if hasattr(target, 'routing') and len(target.routing) > 1: raise RuntimeError('Bridging is not supported yet') tx_data = array.array('B') tx_data.append(netfn << 2 | lun) tx_data.append(self._csum((target.ipmb_address, tx_data[0]))) tx_data.append(self.slave_address) tx_data.append(self.next_sequence_number << 2) tx_data.extend([ord(c) for c in raw_bytes]) tx_data.append(self._csum(tx_data[2:])) addr = target.ipmb_address >> 1 self._dev.i2c_master_write(addr, tx_data.tostring()) log().debug('I2C TX to %02Xh [%s]', addr, ' '.join(['%02x' % b for b in tx_data])) # receive messages start_time = time.time() timeout = self.timeout - (time.time() - start_time) rsp_received = False while not rsp_received and timeout > 0: ret = self._dev.poll(int(timeout * 1000)) if ret == pyaardvark.POLL_NO_DATA: raise TimeoutError() (addr, rx_data) = self._dev.i2c_slave_read() log().debug('I2C RX from %02Xh [%s]', addr, ' '.join(['%02x' % ord(c) for c in rx_data])) rx_data = array.array('B', rx_data) addr <<= 1 if (self._csum((addr, rx_data[0], rx_data[1])) == 0 # hdr csum and self._csum(rx_data[2:]) == 0 # payload csum and addr == self.slave_address and rx_data[0] & ~3 == (tx_data[0] & ~3) | 4 # netfn + 1 and rx_data[2] == target.ipmb_address and rx_data[0] & 3 == tx_data[3] & 3 # rq_lun and rx_data[3] & 3 == tx_data[0] & 3 # rs_lun and rx_data[3] >> 2 == self.next_sequence_number and rx_data[4] == tx_data[4]): # command id rsp_received = True self._inc_sequence_number() timeout = self.timeout - (time.time() - start_time) return rx_data.tostring()
def _run_ipmitool(self, target, ipmitool_cmd): """Legacy call of ipmitool (will be removed in future). """ if not hasattr(self, '_session'): raise RuntimeError('Session needs to be set') cmd = self.IPMITOOL_PATH cmd += (' -I lan') cmd += (' -H %s' % self._session._rmcp_host) cmd += (' -p %s' % self._session._rmcp_port) if hasattr(target, 'routing'): # we have to do bridging here if len(target.routing) == 1: # ipmitool/shelfmanager does implicit bridging cmd += (' -b %d' % target.routing[0].bridge_channel) elif len(target.routing) == 2: cmd += (' -B %d' % target.routing[0].bridge_channel) cmd += (' -T 0x%02x' % target.routing[1].address) cmd += (' -b %d' % target.routing[1].bridge_channel) else: raise RuntimeError('The impitool interface at most double ' 'briding') if target.ipmb_address: cmd += (' -t 0x%02x' % target.ipmb_address) if self._session.auth_type == Session.AUTH_TYPE_NONE: cmd += ' -P ""' elif self._session.auth_type == Session.AUTH_TYPE_PASSWORD: cmd += (' -U "%s"' % self._session._auth_username) cmd += (' -P "%s"' % self._session._auth_password) else: raise RuntimeError('Session type %d not supported' % self._session.auth_type) cmd += (' %s' % ipmitool_cmd) cmd += (' 2>&1') log().debug('Running ipmitool "%s"', cmd) child = Popen(cmd, shell=True, stdout=PIPE) output = child.communicate()[0] log().debug('return with rc=%d, output was:\n%s', child.returncode, output) return output, child.returncode
def send_and_receive(self, msg): """Sends an IPMI request message and waits for its response. `msg` is a IPMI Message containing both the request and response. """ log().debug('IPMI Request [%s]', msg) rx_data = self._send_and_receive(msg.target, msg.lun, msg.netfn, msg.cmdid, encode_message(msg)) msg = create_message(msg.cmdid, msg.netfn + 1) decode_message(msg, rx_data) log().debug('IPMI Response [%s])', msg) return msg
def send_and_receive(self, msg): """Sends an IPMI request message and waits for its response. `msg` is a IPMI Message containing both the request and response. """ log().debug('IPMI Request [%s]', msg) rx_data = self._send_and_receive_raw(msg.target, msg.lun, msg.netfn, chr(msg.cmdid) + encode_message(msg)) msg = create_message(msg.cmdid, msg.netfn + 1) decode_message(msg, rx_data[5:-1]) log().debug('IPMI Response [%s])', msg) return msg
def _rx_filter(self, header, rx_data): log().debug('[%s]' % ' '.join(['%02x' % b for b in rx_data])) checks = [ (checksum(rx_data[0:3]), 0, 'Header checksum failed'), (checksum(rx_data[3:]), 0, 'payload checksum failed'), (rx_data[0], header.rq_sa, 'slave address mismatch'), (rx_data[1] & ~3, header.netfn << 2 | 4, 'NetFn mismatch'), (rx_data[3], header.rs_sa, 'target address mismatch'), (rx_data[1] & 3, header.rq_lun, 'request LUN mismatch'), (rx_data[4] & 3, header.rs_lun & 3, 'responder LUN mismatch'), (rx_data[4] >> 2, header.rq_seq, 'sequence number mismatch'), (rx_data[5], header.cmd_id, 'command id mismatch'), ] match = True for left, right, msg in checks: if left != right: log().debug('%s (%02Xh != %02Xh)' % (msg, left, right)) match = False return match
def _rx_filter(self, rq_sa, rq_lun, rq_seq, rs_sa, rs_lun, netfn, cmd_id, rx_data): match = True if (self._csum((rq_sa, rx_data[0], rx_data[1])) != 0): log().warning('Header checksum failed') match = False if self._csum(rx_data[2:]) != 0: log().warning('payload checksum failed') match = False if rq_sa != self.slave_address: log().debug('slave address mismatch') match = False if rx_data[0] & ~3 != (netfn << 2) | 4: log().debug('NetFn mismatch') match = False if rx_data[2] != rs_sa: log().debug('target address mismatch') match = False if rx_data[0] & 3 != rq_lun: log().debug('request LUN mismatch') match = False if rx_data[3] & 3 != rs_lun & 3: log().debug('responder LUN mismatch') match = False if rx_data[3] >> 2 != rq_seq: log().debug('sequence number mismatch') match = False if rx_data[4] != cmd_id: log().debug('command id mismatch') match = False return match