Manage a Dell Chassis.

    chassis_name
        The name of the chassis.

    datacenter
        The datacenter in which the chassis is located

    location
        The location of the chassis.

    password
        Password for the chassis. Note: If this password is set for the chassis,
        the current implementation of this state will set this password both on
        the chassis and the iDrac passwords on any configured blades. If the
        password for the blades should be distinct, they should be set separately
        with the blade_idrac function.

    mode
        The management mode of the chassis. Viable options are:

        - 0: None
        - 1: Monitor
        - 2: Manage and Monitor

    idrac_launch
        The iDRAC launch method of the chassis. Viable options are:

        - 0: Disabled (launch iDRAC using IP address)
        - 1: Enabled (launch iDRAC using DNS name)

    slot_names
        The names of the slots, provided as a list identified by
        their slot numbers.

    blade_power_states
        The power states of a blade server, provided as a list and
        identified by their server numbers. Viable options are:

         - on: Ensure the blade server is powered on.
         - off: Ensure the blade server is powered off.
         - powercycle: Power cycle the blade server.

    Example:

    .. code-block:: yaml

        my-dell-chassis:
          dellchassis.chassis:
            - chassis_name: my-dell-chassis
            - location: my-location
            - datacenter: london
            - mode: 2
            - idrac_launch: 1
            - slot_names:
              - 1: my-slot-name
              - 2: my-other-slot-name
            - blade_power_states:
              - server-1: on
              - server-2: off
              - server-3: powercycle

def chassis(name, chassis_name=None, password=None, datacenter=None,
            location=None, mode=None, idrac_launch=None, slot_names=None,
            blade_power_states=None):
    '''
    Manage a Dell Chassis.

    chassis_name
        The name of the chassis.

    datacenter
        The datacenter in which the chassis is located

    location
        The location of the chassis.

    password
        Password for the chassis. Note: If this password is set for the chassis,
        the current implementation of this state will set this password both on
        the chassis and the iDrac passwords on any configured blades. If the
        password for the blades should be distinct, they should be set separately
        with the blade_idrac function.

    mode
        The management mode of the chassis. Viable options are:

        - 0: None
        - 1: Monitor
        - 2: Manage and Monitor

    idrac_launch
        The iDRAC launch method of the chassis. Viable options are:

        - 0: Disabled (launch iDRAC using IP address)
        - 1: Enabled (launch iDRAC using DNS name)

    slot_names
        The names of the slots, provided as a list identified by
        their slot numbers.

    blade_power_states
        The power states of a blade server, provided as a list and
        identified by their server numbers. Viable options are:

         - on: Ensure the blade server is powered on.
         - off: Ensure the blade server is powered off.
         - powercycle: Power cycle the blade server.

    Example:

    .. code-block:: yaml

        my-dell-chassis:
          dellchassis.chassis:
            - chassis_name: my-dell-chassis
            - location: my-location
            - datacenter: london
            - mode: 2
            - idrac_launch: 1
            - slot_names:
              - 1: my-slot-name
              - 2: my-other-slot-name
            - blade_power_states:
              - server-1: on
              - server-2: off
              - server-3: powercycle
    '''
    ret = {'name': chassis_name,
           'chassis_name': chassis_name,
           'result': True,
           'changes': {},
           'comment': ''}

    chassis_cmd = 'chassis.cmd'
    cfg_tuning = 'cfgRacTuning'
    mode_cmd = 'cfgRacTuneChassisMgmtAtServer'
    launch_cmd = 'cfgRacTuneIdracDNSLaunchEnable'

    inventory = __salt__[chassis_cmd]('inventory')

    if idrac_launch:
        idrac_launch = six.text_type(idrac_launch)

    current_name = __salt__[chassis_cmd]('get_chassis_name')
    if chassis_name != current_name:
        ret['changes'].update({'Name':
                              {'Old': current_name,
                               'New': chassis_name}})

    current_dc = __salt__[chassis_cmd]('get_chassis_datacenter')
    if datacenter and datacenter != current_dc:
        ret['changes'].update({'Datacenter':
                                   {'Old': current_dc,
                                    'New': datacenter}})

    if password:
        ret['changes'].update({'Password':
                                   {'Old': '******',
                                     'New': '******'}})
    if location:
        current_location = __salt__[chassis_cmd]('get_chassis_location')
        if location != current_location:
            ret['changes'].update({'Location':
                                  {'Old': current_location,
                                   'New': location}})
    if mode:
        current_mode = __salt__[chassis_cmd]('get_general', cfg_tuning, mode_cmd)
        if mode != current_mode:
            ret['changes'].update({'Management Mode':
                                  {'Old': current_mode,
                                   'New': mode}})

    if idrac_launch:
        current_launch_method = __salt__[chassis_cmd]('get_general', cfg_tuning, launch_cmd)
        if idrac_launch != current_launch_method:
            ret['changes'].update({'iDrac Launch Method':
                                  {'Old': current_launch_method,
                                   'New': idrac_launch}})

    if slot_names:
        current_slot_names = __salt__[chassis_cmd]('list_slotnames')
        for s in slot_names:
            key = s.keys()[0]
            new_name = s[key]
            if key.startswith('slot-'):
                key = key[5:]

            current_slot_name = current_slot_names.get(key).get('slotname')
            if current_slot_name != new_name:
                old = {key: current_slot_name}
                new = {key: new_name}
                if ret['changes'].get('Slot Names') is None:
                    ret['changes'].update({'Slot Names':
                                          {'Old': {},
                                           'New': {}}})
                ret['changes']['Slot Names']['Old'].update(old)
                ret['changes']['Slot Names']['New'].update(new)

    current_power_states = {}
    target_power_states = {}
    if blade_power_states:
        for b in blade_power_states:
            key = b.keys()[0]
            status = __salt__[chassis_cmd]('server_powerstatus', module=key)
            current_power_states[key] = status.get('status', -1)
            if b[key] == 'powerdown':
                if current_power_states[key] != -1 and current_power_states[key]:
                    target_power_states[key] = 'powerdown'
            if b[key] == 'powerup':
                if current_power_states[key] != -1 and not current_power_states[key]:
                    target_power_states[key] = 'powerup'
            if b[key] == 'powercycle':
                if current_power_states[key] != -1 and not current_power_states[key]:
                    target_power_states[key] = 'powerup'
                if current_power_states[key] != -1 and current_power_states[key]:
                    target_power_states[key] = 'powercycle'
        for k, v in six.iteritems(target_power_states):
            old = {k: current_power_states[k]}
            new = {k: v}
            if ret['changes'].get('Blade Power States') is None:
                ret['changes'].update({'Blade Power States':
                                      {'Old': {},
                                       'New': {}}})
            ret['changes']['Blade Power States']['Old'].update(old)
            ret['changes']['Blade Power States']['New'].update(new)

    if ret['changes'] == {}:
        ret['comment'] = 'Dell chassis is already in the desired state.'
        return ret

    if __opts__['test']:
        ret['result'] = None
        ret['comment'] = 'Dell chassis configuration will change.'
        return ret

    # Finally, set the necessary configurations on the chassis.
    name = __salt__[chassis_cmd]('set_chassis_name', chassis_name)
    if location:
        location = __salt__[chassis_cmd]('set_chassis_location', location)
    pw_result = True
    if password:
        pw_single = True
        if __salt__[chassis_cmd]('change_password', username='root', uid=1,
                                   password=password):
            for blade in inventory['server']:
                pw_single = __salt__[chassis_cmd]('deploy_password',
                                                  username='root',
                                                  password=password,
                                                  module=blade)
                if not pw_single:
                    pw_result = False
        else:
            pw_result = False

    if datacenter:
        datacenter_result = __salt__[chassis_cmd]('set_chassis_datacenter',
                                                  datacenter)
    if mode:
        mode = __salt__[chassis_cmd]('set_general', cfg_tuning, mode_cmd, mode)
    if idrac_launch:
        idrac_launch = __salt__[chassis_cmd]('set_general', cfg_tuning, launch_cmd, idrac_launch)
    if ret['changes'].get('Slot Names') is not None:
        slot_rets = []
        for s in slot_names:
            key = s.keys()[0]
            new_name = s[key]
            if key.startswith('slot-'):
                key = key[5:]
            slot_rets.append(__salt__[chassis_cmd]('set_slotname', key, new_name))

        if any(slot_rets) is False:
            slot_names = False
        else:
            slot_names = True

    powerchange_all_ok = True
    for k, v in six.iteritems(target_power_states):
        powerchange_ok = __salt__[chassis_cmd]('server_power', v, module=k)
        if not powerchange_ok:
            powerchange_all_ok = False

    if any([name, location, mode, idrac_launch,
            slot_names, powerchange_all_ok]) is False:
        ret['result'] = False
        ret['comment'] = 'There was an error setting the Dell chassis.'

    ret['comment'] = 'Dell chassis was updated.'
    return ret