~ubuntu-branches/ubuntu/vivid/ironic/vivid-updates

« back to all changes in this revision

Viewing changes to ironic/drivers/modules/ipmitool.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2015-01-05 12:21:37 UTC
  • mfrom: (1.2.4)
  • Revision ID: package-import@ubuntu.com-20150105122137-171bqrdpcxqipunk
Tags: 2015.1~b1-0ubuntu1
* New upstream beta release:
  - d/control: Align version requirements with upstream release.
* d/watch: Update uversionmangle to deal with kilo beta versioning
  changes.
* d/control: Bumped Standards-Version to 3.9.6, no changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
 
39
39
from oslo.config import cfg
40
40
from oslo.utils import excutils
 
41
from oslo_concurrency import processutils
41
42
 
42
43
from ironic.common import boot_devices
43
44
from ironic.common import exception
51
52
from ironic.drivers.modules import console_utils
52
53
from ironic.openstack.common import log as logging
53
54
from ironic.openstack.common import loopingcall
54
 
from ironic.openstack.common import processutils
55
55
 
56
56
 
57
57
CONF = cfg.CONF
210
210
    missing_info = [key for key in REQUIRED_PROPERTIES if not info.get(key)]
211
211
    if missing_info:
212
212
        raise exception.MissingParameterValue(_(
213
 
            "The following IPMI credentials are not supplied"
214
 
            " to IPMI driver: %s."
215
 
             ) % missing_info)
 
213
            "Missing the following IPMI credentials in node's"
 
214
            " driver_info: %s.") % missing_info)
216
215
 
217
216
    address = info.get('ipmi_address')
218
217
    username = info.get('ipmi_username')
236
235
    # check if ipmi_bridging has proper value
237
236
    if bridging_type == 'no':
238
237
        # if bridging is not selected, then set all bridging params to None
239
 
        local_address = transit_channel = transit_address = \
240
 
            target_channel = target_address = None
 
238
        (local_address, transit_channel, transit_address, target_channel,
 
239
         target_address) = (None,) * 5
241
240
    elif bridging_type in bridging_types:
242
241
        # check if the particular bridging option is supported on host
243
242
        if not _is_option_supported('%s_bridge' % bridging_type):
355
354
 
356
355
def _sleep_time(iter):
357
356
    """Return the time-to-sleep for the n'th iteration of a retry loop.
 
357
 
358
358
    This implementation increases exponentially.
359
359
 
360
360
    :param iter: iteration number
547
547
    return sensors_data_dict
548
548
 
549
549
 
 
550
@task_manager.require_exclusive_lock
 
551
def _send_raw(task, raw_bytes):
 
552
    """Send raw bytes to the BMC. Bytes should be a string of bytes.
 
553
 
 
554
    :param task: a TaskManager instance.
 
555
    :param raw_bytes: a string of raw bytes to send, e.g. '0x00 0x01'
 
556
    :raises: IPMIFailure on an error from ipmitool.
 
557
    :raises: MissingParameterValue if a required parameter is missing.
 
558
    :raises:  InvalidParameterValue when an invalid value is specified.
 
559
 
 
560
    """
 
561
    node_uuid = task.node.uuid
 
562
    LOG.debug('Sending node %(node)s raw bytes %(bytes)s',
 
563
              {'bytes': raw_bytes, 'node': node_uuid})
 
564
    driver_info = _parse_driver_info(task.node)
 
565
    cmd = 'raw %s' % raw_bytes
 
566
 
 
567
    try:
 
568
        out, err = _exec_ipmitool(driver_info, cmd)
 
569
        LOG.debug('send raw bytes returned stdout: %(stdout)s, stderr:'
 
570
                  ' %(stderr)s', {'stdout': out, 'stderr': err})
 
571
    except (exception.PasswordFileFailedToCreate,
 
572
            processutils.ProcessExecutionError) as e:
 
573
        LOG.exception(_LE('IPMI "raw bytes" failed for node %(node_id)s '
 
574
                      'with error: %(error)s.'),
 
575
                      {'node_id': node_uuid, 'error': e})
 
576
        raise exception.IPMIFailure(cmd=cmd)
 
577
 
 
578
 
550
579
class IPMIPower(base.PowerInterface):
551
580
 
552
581
    def __init__(self):
693
722
        if device not in self.get_supported_boot_devices():
694
723
            raise exception.InvalidParameterValue(_(
695
724
                "Invalid boot device %s specified.") % device)
 
725
 
 
726
        # note(JayF): IPMI spec indicates unless you send these raw bytes the
 
727
        # boot device setting times out after 60s. Since it's possible it
 
728
        # could be >60s before a node is rebooted, we should always send them.
 
729
        # This mimics pyghmi's current behavior, and the "option=timeout"
 
730
        # setting on newer ipmitool binaries.
 
731
        timeout_disable = "0x00 0x08 0x03 0x08"
 
732
        _send_raw(task, timeout_disable)
 
733
 
696
734
        cmd = "chassis bootdev %s" % device
697
735
        if persistent:
698
736
            cmd = cmd + " options=persistent"
792
830
                reason=_("Unable to locate usable ipmitool command in "
793
831
                         "the system path when checking ipmitool version"))
794
832
 
 
833
    @base.passthru(['POST'])
795
834
    @task_manager.require_exclusive_lock
796
 
    def _send_raw_bytes(self, task, raw_bytes):
 
835
    def send_raw(self, task, http_method, raw_bytes):
797
836
        """Send raw bytes to the BMC. Bytes should be a string of bytes.
798
837
 
799
838
        :param task: a TaskManager instance.
 
839
        :param http_method: the HTTP method used on the request.
800
840
        :param raw_bytes: a string of raw bytes to send, e.g. '0x00 0x01'
801
841
        :raises: IPMIFailure on an error from ipmitool.
802
842
        :raises: MissingParameterValue if a required parameter is missing.
803
843
        :raises:  InvalidParameterValue when an invalid value is specified.
804
844
 
805
845
        """
806
 
        node_uuid = task.node.uuid
807
 
        LOG.debug('Sending node %(node)s raw bytes %(bytes)s',
808
 
                  {'bytes': raw_bytes, 'node': node_uuid})
809
 
        driver_info = _parse_driver_info(task.node)
810
 
        cmd = 'raw %s' % raw_bytes
811
 
 
812
 
        try:
813
 
            out, err = _exec_ipmitool(driver_info, cmd)
814
 
            LOG.debug('send raw bytes returned stdout: %(stdout)s, stderr:'
815
 
                      ' %(stderr)s', {'stdout': out, 'stderr': err})
816
 
        except (exception.PasswordFileFailedToCreate,
817
 
                processutils.ProcessExecutionError) as e:
818
 
            LOG.exception(_LE('IPMI "raw bytes" failed for node %(node_id)s '
819
 
                          'with error: %(error)s.'),
820
 
                          {'node_id': node_uuid, 'error': e})
821
 
            raise exception.IPMIFailure(cmd=cmd)
822
 
 
 
846
        _send_raw(task, raw_bytes)
 
847
 
 
848
    @base.passthru(['POST'])
823
849
    @task_manager.require_exclusive_lock
824
 
    def _bmc_reset(self, task, warm=True):
 
850
    def bmc_reset(self, task, http_method, warm=True):
825
851
        """Reset BMC with IPMI command 'bmc reset (warm|cold)'.
826
852
 
827
853
        :param task: a TaskManager instance.
 
854
        :param http_method: the HTTP method used on the request.
828
855
        :param warm: boolean parameter to decide on warm or cold reset.
829
856
        :raises: IPMIFailure on an error from ipmitool.
830
857
        :raises: MissingParameterValue if a required parameter is missing.
868
895
 
869
896
        :param task: a task from TaskManager.
870
897
        :param kwargs: info for action.
871
 
        :raises: InvalidParameterValue if **kwargs does not contain 'method',
872
 
                 'method' is not supported or a byte string is not given for
873
 
                 'raw_bytes'.
 
898
        :raises: InvalidParameterValue when an invalid parameter value is
 
899
                 specified.
874
900
        :raises: MissingParameterValue if a required parameter is missing.
875
901
 
876
902
        """
877
903
        method = kwargs['method']
878
904
        if method == 'send_raw':
879
905
            if not kwargs.get('raw_bytes'):
880
 
                raise exception.InvalidParameterValue(_(
 
906
                raise exception.MissingParameterValue(_(
881
907
                    'Parameter raw_bytes (string of bytes) was not '
882
908
                    'specified.'))
883
 
        elif method == 'bmc_reset':
884
 
            # no additional parameters needed
885
 
            pass
886
 
        else:
887
 
            raise exception.InvalidParameterValue(_(
888
 
                "Unsupported method (%s) passed to IPMItool driver.")
889
 
                % method)
 
909
 
890
910
        _parse_driver_info(task.node)
891
911
 
892
 
    def vendor_passthru(self, task, **kwargs):
893
 
        """Receive requests for vendor-specific actions.
894
 
 
895
 
        Valid methods:
896
 
          * send_raw
897
 
          * bmc_reset
898
 
 
899
 
        :param task: a task from TaskManager.
900
 
        :param kwargs: info for action.
901
 
 
902
 
        :raises: InvalidParameterValue if required IPMI credentials
903
 
            are missing.
904
 
        :raises: IPMIFailure if ipmitool fails for any method.
905
 
        :raises: MissingParameterValue when a required parameter is missing
906
 
 
907
 
        """
908
 
 
909
 
        method = kwargs['method']
910
 
        if method == 'send_raw':
911
 
            return self._send_raw_bytes(task,
912
 
                                        kwargs.get('raw_bytes'))
913
 
        elif method == 'bmc_reset':
914
 
            return self._bmc_reset(task,
915
 
                                   warm=kwargs.get('warm', True))
916
 
 
917
912
 
918
913
class IPMIShellinaboxConsole(base.ConsoleInterface):
919
914
    """A ConsoleInterface that uses ipmitool and shellinabox."""
943
938
        driver_info = _parse_driver_info(task.node)
944
939
        if not driver_info['port']:
945
940
            raise exception.MissingParameterValue(_(
946
 
                "IPMI terminal port not supplied to IPMI driver."))
 
941
                "Missing 'ipmi_terminal_port' parameter in node's"
 
942
                " driver_info."))
947
943
 
948
944
    def start_console(self, task):
949
945
        """Start a remote console for the node.
962
958
        pw_file = console_utils.make_persistent_password_file(
963
959
                path, driver_info['password'])
964
960
 
965
 
        ipmi_cmd = "/:%(uid)s:%(gid)s:HOME:ipmitool -H %(address)s" \
966
 
                   " -I lanplus -U %(user)s -f %(pwfile)s"  \
967
 
                   % {'uid': os.getuid(),
968
 
                      'gid': os.getgid(),
969
 
                      'address': driver_info['address'],
970
 
                      'user': driver_info['username'],
971
 
                      'pwfile': pw_file}
 
961
        ipmi_cmd = ("/:%(uid)s:%(gid)s:HOME:ipmitool -H %(address)s"
 
962
                    " -I lanplus -U %(user)s -f %(pwfile)s"
 
963
                    % {'uid': os.getuid(),
 
964
                       'gid': os.getgid(),
 
965
                       'address': driver_info['address'],
 
966
                       'user': driver_info['username'],
 
967
                       'pwfile': pw_file})
972
968
 
973
969
        for name, option in BRIDGING_OPTIONS:
974
970
            if driver_info[name] is not None: