|
15 | 15 | # |
16 | 16 | # Copyright: 2022 IBM |
17 | 17 | # Authors : Naresh Bannoth <nbannoth@linux.vnet.ibm.com> |
18 | | -# Maram Srimannarayana Murthy<msmurthy@linux.ibm.com> |
19 | 18 |
|
20 | 19 |
|
21 | 20 | """ |
|
27 | 26 | import logging |
28 | 27 | import os |
29 | 28 | import re |
30 | | -import sys |
31 | 29 | import time |
32 | 30 |
|
33 | | -import pexpect # pylint: disable=E0401 |
34 | | - |
35 | 31 | from avocado.utils import pci, process |
36 | 32 |
|
37 | 33 | LOGGER = logging.getLogger(__name__) |
@@ -129,8 +125,7 @@ def get_current_ns_list(controller_name, shared_ns=False): |
129 | 125 | namespaces_ids = get_current_ns_ids(controller_name) |
130 | 126 | if shared_ns: |
131 | 127 | subsys = get_subsystem_using_ctrl_name(controller_name) |
132 | | - controller_name = f"nvme{subsys[len('nvme-subsys'):]}" |
133 | | - |
| 128 | + controller_name = f"nvme{subsys[len('nvme-subsy'):]}" |
134 | 129 | for ns_id in namespaces_ids: |
135 | 130 | namespace_list.append(f"/dev/{controller_name}n{ns_id}") |
136 | 131 | return namespace_list |
@@ -534,206 +529,3 @@ def get_subsystem_using_ctrl_name(ctrl): |
534 | 529 | if ctrl in ctrls: |
535 | 530 | return get_subsys_name_with_nqn(device_nqn) |
536 | 531 | return "" |
537 | | - |
538 | | - |
539 | | -def get_nvme_sed_discover_parameters(namespace): |
540 | | - """ |
541 | | - Fetches values from nvme SED discover command |
542 | | -
|
543 | | - :param namespace: NVMe namespace path |
544 | | - :rtype: dictionary |
545 | | - :raises: NvmeException on command failure |
546 | | - :rtype: dictionary |
547 | | - """ |
548 | | - cmd = f"nvme sed discover {namespace}" |
549 | | - data = process.run(cmd, ignore_status=True, sudo=True, shell=True).stdout_text |
550 | | - pattern = r"\tLocking Supported:\s*(.*)\n\tLocking Feature Enabled:\s*(.*)\n\tLocked:\s*(.*)" |
551 | | - match = re.search(pattern, data, re.MULTILINE) |
552 | | - if match: |
553 | | - locking_features = { |
554 | | - "Locking Supported": match.group(1).strip(), |
555 | | - "Locking Feature Enabled": match.group(2).strip(), |
556 | | - "Locked": match.group(3).strip(), |
557 | | - } |
558 | | - return locking_features |
559 | | - return {} |
560 | | - |
561 | | - |
562 | | -def is_lockdown_supported(namespace): |
563 | | - """ |
564 | | - Fetches information based on namespace |
565 | | - Checks if SED locking is supported for the given namespace |
566 | | -
|
567 | | - :param namespace: NVMe namespace path |
568 | | - :rtype: boolean |
569 | | - """ |
570 | | - lockdown_attr = get_nvme_sed_discover_parameters(namespace) |
571 | | - return lockdown_attr.get("Locking Supported") == "Yes" |
572 | | - |
573 | | - |
574 | | -def is_lockdown_enabled(namespace): |
575 | | - """ |
576 | | - Fetches information based on namespace |
577 | | - Checks if SED locking feature is enabled for the given namespace |
578 | | -
|
579 | | - :param namespace: NVMe namespace path |
580 | | - :rtype: boolean |
581 | | - """ |
582 | | - lockdown_attr = get_nvme_sed_discover_parameters(namespace) |
583 | | - return lockdown_attr.get("Locking Feature Enabled") == "Yes" |
584 | | - |
585 | | - |
586 | | -def is_drive_locked(namespace): |
587 | | - """ |
588 | | - Fetches information based on namespace |
589 | | - Checks if the drive is currently locked for the given namespace |
590 | | -
|
591 | | - :param namespace: NVMe namespace path |
592 | | - :rtype: boolean |
593 | | - """ |
594 | | - lockdown_attr = get_nvme_sed_discover_parameters(namespace) |
595 | | - return lockdown_attr.get("Locked") == "Yes" |
596 | | - |
597 | | - |
598 | | -def initialize_sed_locking(namespace, password): |
599 | | - """ |
600 | | - Enables and initializes SED feature on nvme disk |
601 | | -
|
602 | | - :param namespace: NVMe namespace path |
603 | | - :param password: SED password |
604 | | - """ |
605 | | - if not is_lockdown_supported(namespace): |
606 | | - raise NvmeException(f"SED initialize not supported on {namespace}") |
607 | | - if is_lockdown_enabled(namespace): |
608 | | - raise NvmeException( |
609 | | - f"nvme drive {namespace} locking is enabled, can't initialize it" |
610 | | - ) |
611 | | - pexpect_cmd_execution( |
612 | | - f"nvme sed initialize {namespace}", |
613 | | - [("New Password:", password), ("Re-enter New Password:", password)], |
614 | | - ) |
615 | | - if not is_lockdown_enabled(namespace): |
616 | | - raise NvmeException(f"Failed to initialize nvme disk {namespace}") |
617 | | - |
618 | | - |
619 | | -def revert_sed_locking(namespace, password, destructive=False): |
620 | | - """ |
621 | | - Reverts SED locking state to factory defaults |
622 | | -
|
623 | | - :param namespace: NVMe namespace path |
624 | | - :param password: Current SED password |
625 | | - :raises: NvmeException if revert is not supported, drive is not initialized, |
626 | | - drive is locked, or revert operation fails |
627 | | - """ |
628 | | - if not is_lockdown_supported(namespace): |
629 | | - raise NvmeException(f"Revert not supported on {namespace}") |
630 | | - if not is_lockdown_enabled(namespace): |
631 | | - raise NvmeException( |
632 | | - f"nvme drive {namespace} locking is not enabled, can't revert it" |
633 | | - ) |
634 | | - if is_drive_locked(namespace): |
635 | | - raise NvmeException(f"Reverting not valid when drive is locked {namespace}") |
636 | | - if destructive: |
637 | | - pexpect_cmd_execution( |
638 | | - f"nvme sed revert -e {namespace}", |
639 | | - [ |
640 | | - ("Destructive revert erases drive data. Continue (y/n)?", "y"), |
641 | | - ("Are you sure (y/n)?", "y"), |
642 | | - ("Password:", password), |
643 | | - ], |
644 | | - ) |
645 | | - else: |
646 | | - pexpect_cmd_execution(f"nvme sed revert {namespace}", [("Password:", password)]) |
647 | | - if is_lockdown_enabled(namespace): |
648 | | - raise NvmeException(f"Failed to revert {namespace}") |
649 | | - |
650 | | - |
651 | | -def unlock_drive(namespace, with_pass_key=""): |
652 | | - """ |
653 | | - Unlocks SED locked driver |
654 | | -
|
655 | | - :param namespace: NVMe namespace path |
656 | | - :param with_pass_key: Password for unlocking (if empty, no password prompt) |
657 | | - """ |
658 | | - if not is_drive_locked(namespace): |
659 | | - raise NvmeException(f"Drive is not locked, unlock failed for {namespace}") |
660 | | - cmd = f"nvme sed unlock {namespace}" |
661 | | - if with_pass_key: |
662 | | - cmd = f"{cmd} -k" |
663 | | - pexpect_cmd_execution(cmd, [("Password:", with_pass_key)]) |
664 | | - elif process.system(cmd, shell=True, ignore_status=True): |
665 | | - raise NvmeException(f"namespace {namespace} unlock failed") |
666 | | - if is_drive_locked(namespace): |
667 | | - raise NvmeException(f"Unlock failed for {namespace}") |
668 | | - |
669 | | - |
670 | | -def lock_drive(namespace, with_pass_key=""): |
671 | | - """ |
672 | | - SED lock enables on nvme drive |
673 | | -
|
674 | | - :param namespace: NVMe namespace path |
675 | | - :param with_pass_key: Password for locking (if empty, no password prompt) |
676 | | - """ |
677 | | - if is_drive_locked(namespace): |
678 | | - raise NvmeException(f"namespace {namespace} already in locked state") |
679 | | - cmd = f"nvme sed lock {namespace}" |
680 | | - if with_pass_key: |
681 | | - cmd = f"{cmd} -k" |
682 | | - pexpect_cmd_execution(cmd, [("Password:", with_pass_key)]) |
683 | | - elif process.system(cmd, shell=True, ignore_status=True): |
684 | | - raise NvmeException(f"namespace {namespace} lock failed") |
685 | | - if not is_drive_locked(namespace): |
686 | | - raise NvmeException(f"locking failed for {namespace}") |
687 | | - |
688 | | - |
689 | | -def change_sed_password(namespace, pwd1, pwd2): |
690 | | - """ |
691 | | - Changes the SED password for the specified namespace |
692 | | -
|
693 | | - :param namespace: NVMe namespace path |
694 | | - :param pwd1: Current SED password |
695 | | - :param pwd2: New SED password |
696 | | - :raises: NvmeException if password change is not supported or drive is not initialized |
697 | | - """ |
698 | | - if not is_lockdown_supported(namespace): |
699 | | - raise NvmeException(f"Change password not supported on {namespace}") |
700 | | - if not is_lockdown_enabled(namespace): |
701 | | - raise NvmeException( |
702 | | - f"nvme drive {namespace} is not initialized, can't change password" |
703 | | - ) |
704 | | - pexpect_cmd_execution( |
705 | | - f"nvme sed password {namespace}", |
706 | | - [ |
707 | | - ("Password:", pwd1), |
708 | | - ("New Password:", pwd2), |
709 | | - ("Re-enter New Password:", pwd2), |
710 | | - ], |
711 | | - ) |
712 | | - |
713 | | - |
714 | | -def pexpect_cmd_execution(cmd, list_of_expect_sendline): |
715 | | - """ |
716 | | - Execute command using pexpect with multiple expect/sendline interactions |
717 | | -
|
718 | | - :param cmd: Command to execute |
719 | | - :param list_of_expect_sendline: List of (expect_pattern, sendline_value) tuples |
720 | | - :raises: NvmeException on command failures |
721 | | - """ |
722 | | - try: |
723 | | - LOGGER.info("Executing command using pexpect: %s", cmd) |
724 | | - pexpect_handle = pexpect.spawn(cmd) |
725 | | - pexpect_handle.log_read = sys.stdout |
726 | | - for expect, value in list_of_expect_sendline: |
727 | | - pexpect_handle.expect(expect, timeout=30) |
728 | | - pexpect_handle.sendline(value) |
729 | | - LOGGER.debug("Matched String: %s", pexpect_handle.after.strip()) |
730 | | - LOGGER.debug("Pexpect output: %s", pexpect_handle.before.strip()) |
731 | | - time.sleep(3) |
732 | | - pexpect_handle.close() |
733 | | - LOGGER.info("%s command executed successfully", cmd) |
734 | | - except pexpect.exceptions.TIMEOUT as e: |
735 | | - LOGGER.error("Command timed out: %s", cmd) |
736 | | - raise NvmeException(f"Command timeout: {cmd}") from e |
737 | | - except pexpect.exceptions.EOF as e: |
738 | | - LOGGER.error("Command ended unexpectedly: %s", cmd) |
739 | | - raise NvmeException(f"Command failed unexpectedly: {cmd}") from e |
0 commit comments