Пример #1
0
    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
Пример #2
0
    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
Пример #3
0
    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()
Пример #4
0
    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]
Пример #5
0
    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()
Пример #6
0
    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
Пример #7
0
    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]))
Пример #8
0
    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]))
Пример #9
0
    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
Пример #10
0
    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
Пример #11
0
    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()
Пример #12
0
    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
Пример #13
0
    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
Пример #14
0
    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
Пример #15
0
    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
Пример #16
0
    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