CiscoUcs/imcsdk

View on GitHub
imcsdk/apis/v2/storage/pd.py

Summary

Maintainability
F
5 days
Test Coverage
# Copyright 2017 Cisco Systems, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""
This module provides APIs for physical drive configuration.
"""

import logging

from imcsdk.imcexception import ImcOperationError
from imcsdk.mometa.storage.StorageLocalDisk import StorageLocalDiskConsts
from imcsdk.apis.v2.storage.controller import _get_controller_dn

log = logging.getLogger('imc')


def pd_get(handle,
           controller_type, controller_slot, drive_slot,
           server_id=1):
    """
    Gets the physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        mo = pd_get(handle, controller_type='SAS', controller_slot='HBA',
                    drive_slot=4)
    """
    controller_dn = _get_controller_dn(handle,
                                       controller_type,
                                       controller_slot,
                                       server_id)
    dn = controller_dn + '/pd-' + str(drive_slot)
    return handle.query_dn(dn)


def _pd_set_action(handle, controller_type, controller_slot, drive_slot,
                   action,
                   server_id=1, **kwargs):
    mo = pd_get(handle, controller_type, controller_slot, drive_slot,
                server_id)
    if mo is None:
        raise ImcOperationError("Get Physical drive: %s" % drive_slot,
                                "Not found")
    mo.admin_action = action
    mo.set_prop_multiple(**kwargs)
    handle.set_mo(mo)
    return handle.query_dn(mo.dn)


def pd_set_unconfigured_good(handle,
                             controller_type, controller_slot, drive_slot,
                             server_id=1):
    """
    Sets the physical drive in unconfigured good state

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_unconfigured_good(handle, controller_type='SAS',
                                 controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_MAKE_UNCONFIGURED_GOOD
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_set_jbod(handle,
                controller_type, controller_slot, drive_slot,
                server_id=1):
    """
    Sets the physical drive in jbod mode

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_jbod(handle, controller_type='SAS', controller_slot='HBA',
                    drive_slot=4)
    """
    from imcsdk.apis.v2.storage.controller import controller_jbod_exists

    if not controller_jbod_exists(handle,
                                  controller_type,
                                  controller_slot,
                                  server_id):
        raise ImcOperationError("Enable JBOD mode on Physical drive: %s" % drive_slot,
                                "Controller JBOD mode is not enabled")

    action = StorageLocalDiskConsts.ADMIN_ACTION_MAKE_JBOD
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_set_global_hot_spare(handle,
                            controller_type, controller_slot, drive_slot,
                            server_id=1):
    """
    Sets the physical drive as a global hot spare

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_global_hot_spare(handle, controller_type='SAS',
                                controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_MAKE_GLOBAL_HOT_SPARE
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_set_dedicated_hot_spare(handle, controller_type, controller_slot,
                               drive_slot, vd_id, server_id=1):
    """
    Sets the physical drive as dedicated hot spare

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        vd_id (str): virtual drive id
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_dedicated_hot_spare(handle, controller_type='SAS',
                                   controller_slot='HBA', drive_slot=4, vd_id=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_MAKE_DEDICATED_HOT_SPARE
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id,
            dedicated_hot_spare_for_vd_id=vd_id
        )


def pd_remove_hot_spare(handle,
                        controller_type, controller_slot, drive_slot,
                        server_id=1):
    """
    Removes the physical drive from hot spare pool.

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_remove_hot_spare(handle, controller_type='SAS',
                                controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_REMOVE_HOT_SPARE
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_set_boot_drive(handle,
                      controller_type, controller_slot, drive_slot,
                      server_id=1):
    """
    Sets the physical drive as boot drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_boot_drive(handle, controller_type='SAS',
                          controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_SET_BOOT_DRIVE
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def _pd_exists_boot_drive(handle, pd_dn):
    dn = pd_dn + '/general-props'
    mo = handle.query_dn(dn)
    if mo is None:
        return False
    if mo.boot_drive.lower() != 'true':
        return False
    return True


def pd_set_removal_prepare(handle,
                           controller_type, controller_slot, drive_slot,
                           server_id=1):
    """
    Prepare a drive for removal

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_removal_prepare(handle, controller_type='SAS',
                               controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_PREPARE_FOR_REMOVAL
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_set_removal_undo(handle,
                        controller_type, controller_slot, drive_slot,
                        server_id=1):
    """
    Undo a prepare for removal

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_set_removal_undo(handle, controller_type='SAS',
                            controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_UNDO_PREPARE_FOR_REMOVAL
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_secure_erase_foreign_drives(handle, controller_type, controller_slot,
                                   drive_slot, server_id=1):
    """
    Erases foreign configuration from the physical drive. Drive data is lost.

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_secure_erase_foreign_drives(handle, controller_type='SAS',
                                       controller_slot='HBA', drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_DISABLE_SED_FOREIGN_DRIVES,
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_state_set(handle,
                 controller_type, controller_slot, drive_slot, drive_state,
                 vd_id=None, server_id=1):
    """
    Sets the drive state of physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        drive_state (str): ["unconfigured_good", "jbod", "boot_drive",
                            "global_hot_spare", "dedicated_hot_spare",
                            "remove_hot_spare", "prepare_removal",
                            "undo_prepare_removal"]
        vd_id (int): virtual drive id.
                     Use only if drive_state == dedicated_hot_spare
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_state_set(handle, controller_type='SAS', controller_slot='HBA',
                     drive_slot=4, drive_state="jbod")
    """

    ds_map = {
        "unconfigured_good": pd_set_unconfigured_good,
        "jbod": pd_set_jbod,
        "boot_drive": pd_set_boot_drive,
        "global_hot_spare": pd_set_global_hot_spare,
        "dedicated_hot_spare": pd_set_dedicated_hot_spare,
        "remove_hot_spare": pd_remove_hot_spare,
        "prepare_removal": pd_set_removal_prepare,
        "undo_prepare_removal": pd_set_removal_undo,
    }

    if drive_state not in ds_map:
        raise ImcOperationError("Get Physical drive: %s" % drive_slot,
                                "Invalid drive state. Valid values are  %s"
                                % str(", ".join(ds_map.keys())))

    params = {
        'handle': handle,
        'controller_type': controller_type,
        'controller_slot': controller_slot,
        'drive_slot': drive_slot,
        'vd_id': vd_id,
        'server_id': server_id
    }

    if not drive_state == "dedicated_hot_spare":
        params.pop('vd_id', None)

    execute_api = ds_map[drive_state]
    return execute_api(**params)


def pd_state_exists(handle,
                    controller_type, controller_slot, drive_slot, drive_state,
                    vd_id=None, server_id=1):
    """
    Returns True if the drive state is drive_state else False

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        drive_state (str): ["unconfigured_good", "jbod", "boot_drive",
                            "global_hot_spare", "dedicated_hot_spare",
                            "remove_hot_spare", "prepare_removal",
                            "undo_prepare_removal"]
        vd_id (int): virtual drive id.
                     Use only if drive_state == dedicated_hot_spare
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_state_exists(handle, controller_type='SAS', controller_slot='HBA',
                        drive_slot=4, drive_state='jbod', vd_id=0)
    """

    ds_map = {
        "unconfigured_good": "Unconfigured Good",
        "jbod": "JBOD",
        "boot_drive": None,
        "global_hot_spare": "Global Hot Spare",
        "dedicated_hot_spare": "Dedicated Hot Spare",
        "remove_hot_spare": None,
        "prepare_removal": "Ready to Remove",
        "undo_prepare_removal": None,
    }

    if drive_state not in ds_map:
        raise ImcOperationError("Get Physical drive: %s" % drive_slot,
                                "Invalid drive state. Valid values are  %s"
                                % str(", ".join(ds_map.keys())))

    mo = pd_get(handle, controller_type, controller_slot, drive_slot,
                server_id)
    if mo is None:
        return False, None

    mo_drive_state = mo.pd_status
    expected_drive_state = ds_map[drive_state]

    if drive_state == "boot_drive":
        return _pd_exists_boot_drive(handle, mo.dn), mo

    if expected_drive_state is None:
        return False, mo
    return mo_drive_state == expected_drive_state, mo


def pd_encryption_capable(handle, controller_type, controller_slot, drive_slot,
                          server_id=1):
    """
    Checks if encryption is supported on the physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        bool

    Examples:
        capable = pd_encryption_capable(handle, controller_type='SAS',
                                        controller_slot='HBA',
                                        drive_slot=4)
    """
    mo = pd_get(handle, controller_type, controller_slot, drive_slot,
                server_id)
    if mo is None:
        raise ImcOperationError("Get Physical drive:%s" % drive_slot,
                                "Not found")
    return mo.fde_capable.lower() in ['yes', 'true']


def pd_encryption_enable(handle,
                         controller_type, controller_slot, drive_slot,
                         server_id=1):
    """
    Enables encryption on the physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_encryption_enable(handle, controller_type='SAS',
                             controller_slot='HBA', drive_slot=4)
    """
    # pre-requisite
    # 1) disk should be encryption capable
    capable = pd_encryption_capable(handle, controller_type, controller_slot,
                                    drive_slot, server_id)
    if not capable:
        raise ImcOperationError("Enable encryption on the Physical drive: %s" % drive_slot,
                                "Drive is not FDE capable.")

    # 2) disk should be in JBOD mode.
    pd = pd_get(handle, controller_type, controller_slot, drive_slot,
                server_id)
    if pd.drive_state != "JBOD":
        raise ImcOperationError("Enable encryption on the Physical drive: %s" % drive_slot,
                                "Drive is not in JBOD mode")

    action = StorageLocalDiskConsts.ADMIN_ACTION_ENABLE_SELF_ENCRYPT
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )


def pd_encryption_exists(handle, controller_type, controller_slot, drive_slot,
                         server_id=1):
    """
    Checks if encryption is enabled on the physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        True/False, MO/None

    Examples:
        enabled = pd_encryption_exists(handle, controller_type='SAS',
                                       controller_slot='HBA', drive_slot=4)
    """
    mo = pd_get(handle, controller_type, controller_slot, drive_slot,
                server_id)
    if mo is None:
        return False, None

    if mo.fde_enabled.lower() not in ['yes', 'true']:
        return False, mo

    return True, mo


def pd_encryption_disable(handle, controller_type, controller_slot, drive_slot,
                          server_id=1):
    """
    Disables encryption on the physical drive

    Args:
        handle (ImcHandle)
        controller_type (str): Controller type
                               'SAS'
        controller_slot (str): Controller slot name/number
                                "MEZZ","0"-"9", "HBA"
        drive_slot (int): Slot in which the drive resides
        server_id (int): server_id for UCS 3260 platform

    Returns:
        StorageLocalDisk object

    Examples:
        pd_encryption_disable(handle, controller_type='SAS',
                              controller_slot='HBA',
                              drive_slot=4)
    """
    action = StorageLocalDiskConsts.ADMIN_ACTION_DISABLE_SELF_ENCRYPT
    return _pd_set_action(
            handle,
            controller_type=controller_type,
            controller_slot=controller_slot,
            drive_slot=drive_slot,
            action=action,
            server_id=server_id
        )