iLO-manager first main commitgit status

This commit is contained in:
Jiří Stach committed 2026-02-03 15:56:53 +01:00
1 parent e6f4cc04ca
commit 599d8da562
3271 files changed
+550655

No files matched your search

Whitespace-only changes.
@@ -0,0 +1,228 @@
"""
conftest.py is used to set up shared fixtures, plugins, hooks, other config etc.
This is the functional test conftest.py
http://docs.pytest.org/en/latest/writing_plugins.html#conftest-py-local-per-directory-plugins
"""
from __future__ import absolute_import
import os
import re
import sys
from contextlib import contextmanager
import pytest
import redfish
# For cross-compatibility between Python 2 and Python 3
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse
from ..conftest import RDMC_FILE
from . import utils
from .ilomock import MockServer
@pytest.fixture(scope='session')
def mock_server():
with MockServer() as server:
yield server
@pytest.fixture
def dl360_large(mock_server):
"""Returns a mock server config:
- DL360 Gen10
- 1x AEP DIMM
- 1x DRAM DIMM
"""
data_dir = os.path.join(os.path.dirname(__file__), 'mockdata/dl360-large')
mock_server.load(data_dir)
return MockServerConfig(mock_server, username='rev', password='hpe123')
@pytest.fixture
def dl360_memfast_disabled(dl360_large):
"""Returns a dl360_configured config with MemFastTraining disabled
"""
dl360_large.patch('/redfish/v1/systems/1/bios/settings/', {'Attributes': {'MemFastTraining': 'Disabled'}})
return dl360_large
@pytest.fixture(scope='session')
def test_server():
"""Returns a server config specified by the TEST_SERVER environment variable.
TEST_SERVER should be a URL with optional auth, e.g. https://user:password@host:port
"""
if 'TEST_SERVER' not in os.environ:
pytest.skip("TEST_SERVER not set")
url, username, password = utils.urlparse_auth(os.getenv('TEST_SERVER'))
# If no credentials, then populate with hard-coded values. Credentials required by ilorest.
username = "orange" if username is None else username
password = "password" if password is None else password
return ServerConfig(url=url, username=username, password=password)
@pytest.fixture
def ilorest(tmpdir):
"""Returns an ilorest session (in scripting mode by default).
Each ilorest session receives its own unique temporary cache directory.
"""
yield Ilorest(cache_dir=tmpdir.dirname)
tmpdir.remove(ignore_errors=True)
class ServerConfig(object):
def __init__(self, url=None, username=None, password=None):
self.url = url
self.username = username
self.password = password
@property
def config(self):
return self.url, self.username, self.password
@property
def hostname(self):
parts = urlparse(self.url)
hostname = parts.hostname if parts.scheme else self.url
return hostname
class MockServerConfig(ServerConfig):
def __init__(self, server, username=None, password=None):
super(MockServerConfig, self).__init__(url=server.url, username=username, password=password)
self.server = server
def patch(self, path, data):
"""Patches a resource in the mock server."""
self.server.patch(path, data)
class Ilorest(object):
"""Wrapper for the iLO RESTful Interface Tool."""
def __init__(self, cache_dir=None):
"""Starts ilorest in scripting mode.
:param cache_dir: directory to use for caching instead of the default global location
"""
self.cache_dir = cache_dir
self.args = [sys.executable, RDMC_FILE]
if cache_dir:
self.args.append('--cache-dir={}'.format(cache_dir))
self.interactive = False
self.proc = None
self.prompt = "iLOrest > "
def run(self, args, sendline=None):
"""Runs an ilorest command.
:param args: list of command arguments
:param sendline: string to send after running (only used in interactive mode)
:return: results of the command as a named tuple: (stdout, stderr, retcode)
"""
if not self.interactive:
return utils.run_cmd(self.args + args)
# interactive mode
cmd_line = ' '.join(args)
self.proc.sendline(cmd_line)
if sendline:
self.proc.sendline(sendline)
stdout, stderr = self.proc.read(expect=self.prompt)
match = re.search("iLOrest return code: ([0-9]+)\n", stdout)
retcode = int(match.group(1)) if match else None
return utils.CommandResult(stdout=stdout, stderr=stderr, retcode=retcode)
def login(self, url=None, username=None, password=None):
"""Logs in to the server and establishes a secure session.
:param url: iLO server url if connecting remotely
:param username: iLO username. If no username specified, use "orange"
:param password: iLO password. If no password specified, use "password"
"""
args = ['login']
if url:
args.append(url)
if username:
args.extend(['-u', username])
if password:
args.extend(['-p', password])
results = self.run(args)
assert results.retcode == 0, "Failed to connect or log in"
def logout(self):
"""Ends the current session and disconnects from the server."""
self.run(['logout'])
@contextmanager
def session(self, url=None, username=None, password=None):
"""Establishes a session with an iLO server and logs out afterwards."""
self.login(url=url, username=username, password=password)
yield self
self.logout()
@contextmanager
def interactive_session(self, url=None, username=None, password=None):
"""Establishes an interactive session with an iLO server, and logs out and exits afterwards."""
with self.interactive_mode(), self.session(url=url, username=username, password=password):
yield self
@contextmanager
def interactive_mode(self):
"""Enters interactive mode and exits afterwards."""
# use --verbose to extract the return code
self.proc = utils.InteractivePopen(self.args + ['--verbose'])
self.proc.read(expect=self.prompt)
self.interactive = True
yield self
self.proc.communicate('exit')
self.interactive = False
class RestClient(object):
"""REST client for an iLO server."""
def __init__(self, url=None, username=None, password=None):
"""Initializes an iLO REST client.
:param url: iLO server url if connecting remotely
:param username: iLO username
:param password: iLO password
"""
# if no scheme/protocol defined, try https
if "://" not in url:
url = "https://" + url
self._client = redfish.redfish_client(base_url=url, username=username, password=password)
self._client.login(auth=redfish.AuthMethod.BASIC)
def get(self, path):
"""Sends a GET request."""
resp = self._client.get(path)
return resp.dict
def patch(self, path, body):
"""
Sends a PATCH request to the path with the given body
:param path: URI path
:param body: the body of the patch. For example dict:{ "Attributes": { "Prop1": true } }
:return: RestResponse status, RestResponse dictionary
"""
rest_response = self._client.patch(path=path, body=body)
return rest_response.status, rest_response.dict
@@ -0,0 +1,97 @@
"""ilomock module"""
from __future__ import absolute_import
import os
import subprocess
import sys
import requests
JAVA_BIN = os.getenv('JAVA_BIN', 'java')
ILOMOCK_JAR = os.getenv('ILOMOCK_JAR')
os.environ['NO_PROXY'] = 'localhost'
# ignore SSL warnings
# requests.packages.urllib3.disable_warnings()
class MockServerError(Exception):
"""An error occurred starting the mock server."""
class MockServer(object):
"""Wrapper for ilomock."""
def __init__(self, profile_dir=None, port=0):
"""Initializes a mock server.
:param profile_dir: path to the server profile to use
:param port: port to listen on
"""
self.profile_dir = profile_dir
self.port = port
self.url = None
self.proc = None
def start(self):
"""Starts the mock server.
:raises MockServerError: if the server failed to start
"""
if not ILOMOCK_JAR:
raise MockServerError("ILOMOCK_JAR must be set")
sys.stdout.write("Starting mock server on port {} with profile {}".format(self.port, self.profile_dir))
args = [JAVA_BIN, '-jar', ILOMOCK_JAR, '-p', str(self.port)]
if self.profile_dir:
args.extend(['-s', self.profile_dir])
if not os.path.exists(JAVA_BIN):
raise IOError("JAVA_BIN location does not exist: {}".format(JAVA_BIN))
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# Block until the server starts or fails
output = []
for line in iter(proc.stdout.readline, ''):
output.append(line)
prefix = "Listening on port "
if line.startswith(prefix):
self.proc = proc
self.port = int(line[len(prefix):])
self.url = "https://localhost:{}".format(self.port)
return
proc.communicate()
output = ''.join(output)
raise MockServerError("Failed to start ilomock: {}\n{}".format(proc.returncode, output))
def stop(self):
"""Stops the running mock server."""
if self.proc:
self.proc.kill()
self.proc = None
self.url = None
def __enter__(self):
"""Starts the mock server and returns it."""
self.start()
return self
def __exit__(self, exc_type, exc_value, traceback):
"""Ensures the running mock server stops."""
self.stop()
def patch(self, path, data):
"""Patches a resource in the mock server."""
payload = {'path': path, 'data': data}
resp = requests.post(self.url + '/admin/patch', json=payload, verify=False)
assert resp.status_code == 200, "Failed to patch mock server: {}\n{}"\
.format(resp.status_code, resp.text)
def load(self, profile_dir):
"""Loads a new server profile while the mock server is running."""
config = {'serverProfile': profile_dir}
resp = requests.post(self.url + '/admin/load', json=config, verify=False)
assert resp.status_code == 200, "Failed to load mock server: {}\n{}"\
.format(resp.status_code, resp.text)
@@ -0,0 +1,37 @@
"""Module containing functional tests for the all flag"""
from __future__ import absolute_import
import sys
import pytest
from rdmc_helper import ReturnCodes
@pytest.mark.skip(reason="temporarily remove all flag")
class TestAllFlag(object):
"""Functional Tests for the --all | -a flag"""
@staticmethod
def test_all_flag(ilorest, dl360_large):
"""Test for --all flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--all'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_all_flag_with_json(ilorest, dl360_large):
"""Test for --all flag with --json flag specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--all', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@@ -0,0 +1,141 @@
"""Module containing functional tests for the 'applydcpmmconfig' command"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestApplyPmemConfigCommand(object):
"""Class for functional tests for the applydcpmmconfig command"""
@staticmethod
def test_show_invalid_flag(ilorest):
"""Test function call with invalid flag"""
results = ilorest.run(['applydcpmmconfig', '--bad-flag'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_show_help_flag(ilorest):
"""Test function call with help flag"""
results = ilorest.run(['applydcpmmconfig', '-h'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_no_flag(ilorest):
"""Test for the case when `applydcpmmconfig` command is run without any flag"""
results = ilorest.run(['applydcpmmconfig'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_force_flag_1(ilorest):
"""Test for the case when `applydcpmmconfig` command is run with force flag"""
results = ilorest.run(['applydcpmmconfig', '-f'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_force_flag_2(ilorest):
"""Test for the case when `applydcpmmconfig` command is run with force flag"""
results = ilorest.run(['applydcpmmconfig', '-L', '-f'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
# Cannot test for the positive case - mock server not accepting delete tasks.
@staticmethod
def test_with_force_flag_3(ilorest, dl360_large):
"""Test for the case when `applydcpmmconfig` command is run with force flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['applydcpmmconfig', '-C', 'MemoryMode', '-f'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.NO_CHANGES_MADE_OR_FOUND
@staticmethod
def test_with_config_flag_1(ilorest, dl360_large):
"""Test for the case when `applydcpmmconfig` command is run with config flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['applydcpmmconfig', '-C'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_config_flag_2(ilorest, dl360_large):
"""Test for the case when `applydcpmmconfig` command is run with config flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['applydcpmmconfig', '-C', 'xyz'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_config_flag_3(ilorest, dl360_large):
"""Test for the case when `applydcpmmconfig` command is run with config flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['applydcpmmconfig', '-C', 'AppDirectInterleaved'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.NO_CHANGES_MADE_OR_FOUND
@staticmethod
def test_with_list_flag(ilorest):
"""Test for the case when `applydcpmmconfig` command is run with list flag"""
results = ilorest.run(['applydcpmmconfig', '-L'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_extra_attributes_1(ilorest):
"""Test for the case when `applydcpmmconfig` command is run with extraneous attributes"""
results = ilorest.run(['applydcpmmconfig', '-L', '1qazxcsd'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_extra_attributes_2(ilorest, dl360_large):
"""Test for the case when `applydcpmmconfig` command is run with extraneous attributes"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['applydcpmmconfig', '-C', 'AppDirectInterleaved', '1qazxcsd'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@@ -0,0 +1,52 @@
"""Module containing functional tests for the 'cleardcpmmpendingconfig' command"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestClearDcpmmPendingConfigCommand(object):
"""Class for functional tests for the cleardcpmmpendingconfig command"""
@staticmethod
def test_show_invalid_flag(ilorest):
"""Test function call with invalid flag"""
results = ilorest.run(['cleardcpmmpendingconfig', '--bad-flag'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_show_help_flag(ilorest):
"""Test function call with help flag"""
results = ilorest.run(['cleardcpmmpendingconfig', '-h'])
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_without_flag(ilorest, dl360_large):
"""Test for the case when `cleardcpmmpendingconfig` command is run without any flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['cleardcpmmpendingconfig'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_extraneous_attributes(ilorest):
"""
Test for the case when `cleardcpmmpendingconfig` command is run with extraneous attributes
"""
results = ilorest.run(['cleardcpmmpendingconfig', 'testargument'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@@ -0,0 +1,88 @@
"""Module containing functional tests for the config flag"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestConfigFlag(object):
"""Functional Tests for the --config | -C flag"""
@staticmethod
def test_with_no_dimm_id(ilorest, dl360_large):
"""Test for --config flag with no DIMM IDs specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_valid_dimm_id(ilorest, dl360_large):
"""Test for --config flag with valid DIMM IDs specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config', '--dimm', '1@2,2@3'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_non_pmem_dimm_id(ilorest, dl360_large):
"""Test for --config flag with valid non pmem DIMM IDs specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config', '--dimm', '1@5'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_json_format_1(ilorest, dl360_large):
"""Test for --config flag with --json flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config', '--dimm', '1@2,2@3', '-j'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_json_format_2(ilorest, dl360_large):
"""Test for --config flag with --json flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config', '-j'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_invalid_member_dimm_id(ilorest, dl360_large):
"""Test for --config flag with invalid DIMM IDs specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--config', '--dimm', '8@15'])
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_invalid_dimm_id(ilorest):
"""Test for --config flag with invalid DIMM IDs specified"""
results = ilorest.run(['showdcpmm', '--config', '--dimm', '132,243,xyz'])
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@@ -0,0 +1,111 @@
"""Module containing functional tests for the device flag"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestDeviceFlag(object):
"""Functional Tests for the --device | -D flag"""
@staticmethod
def test_with_no_dimm_id(ilorest, dl360_large):
"""Test for --device flag with no DIMM IDs specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_valid_non_pmem_dimm_id(ilorest, dl360_large):
"""
Test for --device flag with valid DIMM IDs
which are not Persistent Memory Modules specified
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device', '--dimm', '1@1,2@3'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_invalid_dimm_id_1(ilorest):
"""
Test for --device flag with invalid DIMM IDs specified.
Fails at Validation.
"""
results = ilorest.run(['showdcpmm', '--device', '--dimm', '132,243,xyz'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_invalid_dimm_id_2(ilorest, dl360_large):
"""
Test for --device flag with invalid DIMM IDs specified
Passes Validation, Fails later when DIMM IDs not found
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device', '--dimm', '8@2,2@18'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_valid_pmem_dimm_id(ilorest, dl360_large):
"""
Test for --device flag with valid DIMM IDs
which are Persistent Memory Modules specified
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device', '--dimm', '1@2'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_valid_pmem_dimm_id_json(ilorest, dl360_large):
"""
Test for --device flag with valid DIMM IDs
which are Persistent Memory Modules specified
along with the --json flag
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device', '--dimm', '1@2', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_json(ilorest, dl360_large):
"""
Test for --device flag with valid DIMM IDs
which are Persistent Memory Modules specified
along with the --json flag
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--device', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@@ -0,0 +1,62 @@
"""Module containing functional tests for the device flag"""
from __future__ import absolute_import
import sys
import pytest
from rdmc_helper import ReturnCodes
@pytest.mark.skip(reason="temporarily remove display flag")
class TestDisplayFlag(object):
"""Functional Tests for the --display | -d flag"""
@staticmethod
def test_with_no_display_attributes(ilorest):
"""Test for --display flag with no display attributes"""
results = ilorest.run(['showdcpmm', '--display'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_invalid_display_attributes(ilorest, dl360_large):
"""Test for --display flag with invalid display attributes"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--display', 'xyz,abc'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_valid_display_attributes(ilorest, dl360_large):
"""Test for --display flag with valid display attributes"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--display', 'DeviceLocator'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_valid_display_attributes_json(ilorest, dl360_large):
"""
Test for --display flag with valid display attributes
along with the --json flag
"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--display', 'DeviceLocator', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@@ -0,0 +1,44 @@
"""Module containing functional tests for the logical flag"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestLogicalFlag(object):
"""Functional Tests for the --logical | -L flag"""
@staticmethod
def test_with_no_attributes(ilorest, dl360_large):
"""Test for --logical flag with no attributes specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--logical'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_dimm_flag(ilorest):
"""Test for --logical flag with dimm flag specified"""
results = ilorest.run(['showdcpmm', '--logical', '--dimm', '1@2'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_json_flag(ilorest, dl360_large):
"""Test for --logical flag with --json flag specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--logical', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@@ -0,0 +1,133 @@
"""
Functional tests for the command to show the DCPMMs
"""
from __future__ import absolute_import
import sys
import pytest
from jsonpointer import resolve_pointer
from pmemtests.functional.conftest import RestClient
from rdmc_helper import ReturnCodes
class TestShowDcPmemCommand(object):
"""Class for functional tests for the command to enable and disable the scalable pmem feature"""
@staticmethod
def test_show_invalid_flag(ilorest):
""" test function call with invalid flag """
results = ilorest.run(['showdcpmm', '--bad-flag'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_show_help_flag(ilorest):
""" test function call with help flag """
results = ilorest.run(['showdcpmm', '-h'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_showdcpmm_no_flag(ilorest, dl360_large):
"""Test for the case when `showdcpmm` command is run without any flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_showdcpmm_dimm_flag_1(ilorest):
"""Test for the case when `showdcpmm` command is run with dimm flag"""
results = ilorest.run(['showdcpmm', '--dimm'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_showdcpmm_dimm_flag_2(ilorest, dl360_large):
"""Test for the case when `showdcpmm` command is run with dimm flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--dimm', '1@2'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_showdcpmm_dimm_flag_3(ilorest, dl360_large):
"""Test for the case when `showdcpmm` command is run with dimm flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--dimm', '1@2', '2@3'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
@pytest.mark.skip(reason="temporarily remove display flag")
def test_all_and_display_flags(ilorest):
"""Test for the case when --all and --display flags are specified together"""
results = ilorest.run(['showdcpmm', '--all', '--display', 'xyz'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_device_and_config_flags(ilorest):
"""Test for the case when --device and --config flags are specified together"""
results = ilorest.run(['showdcpmm', '--device', '--config'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_logical_and_summary_flags(ilorest):
"""Test for the case when --summary and --logical flags are specified together"""
results = ilorest.run(['showdcpmm', '--logical', '--summary'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_example(ilorest, dl360_large):
""" this is just an example to show using the RestClient """
url, username, password = dl360_large.config
# run ilorest rawget
with ilorest.session(url, username, password):
results = ilorest.run(['rawget', '/redfish/v1/systems/1/bios/settings'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
# check REST attributes
client = RestClient(url, username, password)
bios_settings = client.get('/redfish/v1/systems/1/bios/settings')
sys.stdout.write(str(bios_settings))
assert resolve_pointer(bios_settings, '/Attributes/MemFastTraining') == "Enabled"
@@ -0,0 +1,66 @@
"""Module containing functional tests for the showdcpmmpendingconfig command"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestShowDcpmmPendingConfigCommand(object):
"""Class for functional tests for the showdcpmmpendingconfig command"""
@staticmethod
def test_show_invalid_flag(ilorest):
"""Test function call with invalid flag"""
results = ilorest.run(['showdcpmmpendingconfig', '--bad-flag'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_show_help_flag(ilorest):
"""Test function call with help flag"""
results = ilorest.run(['showdcpmmpendingconfig', '-h'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_no_flag(ilorest, dl360_large):
"""Test for the case when `showdcpmmpendingconfig` command is run without any flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmmpendingconfig'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_json_flag(ilorest, dl360_large):
"""Test for the case when `showdcpmmpendingconfig` command is run with json flag"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmmpendingconfig', '-j'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_extraneous_attributes(ilorest):
"""
Test for the case when `showdcpmmpendingconfig` command is run with extraneous attributes
"""
results = ilorest.run(['showdcpmmpendingconfig', '1qazxcsd'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@@ -0,0 +1,44 @@
"""Module containing functional tests for the summary flag"""
from __future__ import absolute_import
import sys
from rdmc_helper import ReturnCodes
class TestSummaryFlag(object):
"""Functional Tests for the --summary | -M flag"""
@staticmethod
def test_with_no_attributes(ilorest, dl360_large):
"""Test for --summary flag with no attributes specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--summary'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@staticmethod
def test_with_dimm_flag(ilorest):
"""Test for --summary flag with dimm flag specified"""
results = ilorest.run(['showdcpmm', '--summary', '--dimm', '1@2'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.INVALID_COMMAND_LINE_ERROR
@staticmethod
def test_with_json_flag(ilorest, dl360_large):
"""Test for --summary flag with --json flag specified"""
url, username, password = dl360_large.config
with ilorest.session(url, username, password):
results = ilorest.run(['showdcpmm', '--summary', '--json'])
sys.stdout.write("results.stdout: ")
sys.stdout.write(results.stdout)
sys.stdout.write("results.stderr: ")
sys.stdout.write(results.stderr)
assert results.retcode == ReturnCodes.SUCCESS
@@ -0,0 +1,110 @@
"""Utilities for functional tests"""
from __future__ import absolute_import
import os
import subprocess
import tempfile
import time
from collections import namedtuple
# For cross-compatibility between Python 2 and Python 3
try:
from urllib.parse import urlparse
except ImportError:
from urlparse import urlparse
CommandResult = namedtuple('CommandResult', ('stdout', 'stderr', 'retcode'))
def run_cmd(args):
"""Runs a shell command.
:param args: list of command arguments
:return: results of the command as a named tuple: (stdout, stderr, retcode)
"""
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()
retcode = proc.returncode
return CommandResult(stdout=stdout, stderr=stderr, retcode=retcode)
def urlparse_auth(url):
"""Extracts the auth section from a URL (e.g. https://user:password@host)."""
parts = urlparse(url)
username = parts.username
password = parts.password
netloc = parts.netloc.split('@')[-1]
url = parts._replace(netloc=netloc).geturl()
return url, username, password
class InteractivePopen(object):
"""Interactive subprocess Popen."""
def __init__(self, args):
"""Launches an interactive shell as a subprocess.
:param args: sequence of command arguments or a single string
"""
fout = tempfile.NamedTemporaryFile('wb', delete=False)
ferr = tempfile.NamedTemporaryFile('wb', delete=False)
self.fout = open(fout.name, 'r')
self.ferr = open(ferr.name, 'r')
self.proc = subprocess.Popen(args, stdout=fout, stderr=ferr, stdin=subprocess.PIPE)
def communicate(self, input=None):
"""Interacts with the process and waits for it to terminate.
:param input: data to send to stdin
:return: named tuple of (stdout, stderr, retcode)
"""
self.proc.communicate(input)
stdout, stderr = self.read()
retcode = self.proc.returncode
# clean up
self.fout.close()
self.ferr.close()
os.remove(self.fout.name)
os.remove(self.ferr.name)
return CommandResult(stdout=stdout, stderr=stderr, retcode=retcode)
def send(self, str):
"""Sends data to stdin."""
self.proc.stdin.write(str)
def sendline(self, line=""):
"""Sends a newline-terminated string to stdin."""
self.send(line + '\n')
def read(self, expect=None, timeout=60, poll_interval=0.1):
"""Reads from stdout and stderr.
The read is non-blocking unless 'expect' is specified.
:param expect: string to match in stdout before finishing the read
:param timeout: time to wait for the expected string, in seconds
:param poll_interval: poll interval, in seconds
:return: tuple of (stdout, stderr)
"""
stdout = ""
stderr = ""
time_timeout = time.time() + timeout
while True:
out = self.fout.read()
err = self.ferr.read()
if out:
stdout += out
if err:
stderr += err
if expect is None or expect in stdout:
break
if time.time() > time_timeout:
break
time.sleep(poll_interval)
return stdout, stderr