././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/0000775000175000017500000000000000000000000014550 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/.stestr.conf0000664000175000017500000000006600000000000017023 0ustar00zuulzuul00000000000000[DEFAULT] test_path=./sushy_oem_idrac/tests top_dir=. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/AUTHORS0000664000175000017500000000063300000000000015622 0ustar00zuulzuul00000000000000Aija Jauntēva Devendra Kulkarni Dhuldev Valekar DhuldevValekar3 Ilya Etingof Mahendra Kamble Riccardo Pittau Richard Pioso erbarr sonali bhausaheb borkar ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/CONTRIBUTING.rst0000664000175000017500000000123100000000000017206 0ustar00zuulzuul00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: http://docs.openstack.org/infra/manual/developers.html If you already have a good understanding of how the system works and your OpenStack accounts are set up, you can skip to the development workflow section of this documentation to learn how changes to OpenStack should be submitted for review via the Gerrit tool: http://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed in StoryBoard, not GitHub: https://storyboard.openstack.org/#!/project/960 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/ChangeLog0000664000175000017500000000532500000000000016327 0ustar00zuulzuul00000000000000CHANGES ======= 5.0.0 ----- * Add OEM storage controller extension * Update .gitreview after project rename * Add Python3 Zed unit tests 4.0.0 ----- * Migrate constants to enums * Re-add python 3.6/3.7 in classifier * Add destructive field flag to export configuration * Updating yoga tested python versions in classifier * Fix moved tests * Update unit test folder structure * Update min tox version * Add Python3 Yoga unit tests 3.0.1 ----- * Exclude BOSS controllers in clear\_foreign\_config 3.0.0 ----- * Add OEM Task extension * Fix exposing system constants * Update default IncludeInExport value * Add RAID clear foreign config method * Fix IncludeInExport allowed value validation * Add RAID mode conversion methods * Update set\_virtual\_boot\_device for no manager * Increase version of hacking and pycodestyle * Add Flake8 W503 ignore * Enable coverage HTML output * Fix missing Target@Redfish.AllowableValues * Add Python3 Xena unit tests * setup.cfg: Replace dashes with underscores * Use TOX\_CONSTRAINTS\_FILE * Expose manager constants 2.1.0 ----- * Add reset iDRAC method * Update RETRY\_COUNT for virtual media boot * Update virtual media boot-related constants 2.0.0 ----- * Update export system configuration * Add import system configuration method * Update export system config class and constants * Add real-time status check to Lifecycle service * Add resources to put iDRAC in known good state * Add get PXE port MACs for BIOS mode * Add export system configuration * Remove lower constraints * Fix lower-constraints with the new pip resolver 1.0.0 ----- * Use safe version of hacking * Use wallaby CI tests * Fix GET HTTP 202 status without Location * Use victoria tests * Python 3 only * Add pep8 import order check * Switch to the new canonical constraints URL on master * Bump hacking to 3.0.0 * Drop support for Python 2.7 * Bump sushy requirements to 2.0.0+ * Add basic CI jobs and .gitreview * Summon Zuul * Reduce debug verbosity * Improve async call debugging * Reduce async task poll period * Remove autogenerated Changelog from git * Shorten Redfish task service poll period 0.0.2 ----- * Indicate package description is in markdown format 0.0.1 ----- * Rename package to \`sushy-oem-idrac\` * Rephrase package maturity status * Update README * Update unit test to match changed implementation * Align vmedia integration test with ironic behaviour * Support \`permanent\` option of \`set\_virtual\_boot\_device\` * Make ImportConfiguration functional * Rename reboot -> utils * Add missing test case * Add functional virtual media boot test * Add primitive Redfish task monitor * Progress with \`set\_virtual\_boot\_device\` action call * Accommodate changed sushy OEM architecture * Initial revision * Initial commit ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/HACKING.rst0000664000175000017500000000020400000000000016342 0ustar00zuulzuul00000000000000Sushy Style Commandments ======================== Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/LICENSE0000664000175000017500000002363700000000000015570 0ustar00zuulzuul00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/PKG-INFO0000664000175000017500000000517100000000000015651 0ustar00zuulzuul00000000000000Metadata-Version: 2.1 Name: sushy-oem-idrac Version: 5.0.0 Summary: Dell EMC iDRAC OEM extension package for the sushy library Home-page: https://docs.openstack.org/sushy/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: Dell EMC OEM extension for sushy ================================ Sushy is a client [library](https://github.com/openstack/sushy) designed to communicate with [Redfish](https://en.wikipedia.org/wiki/Redfish_(specification)) based BMC. Redfish specification offers extensibility mechanism to let hardware vendors introduce their own features with the common Redfish framework. At the same time, `sushy` supports extending its data model by loading extensions found within its "oem" namespace. The `sushy-oem-idrac` package is a sushy extension package that aims at adding high-level hardware management abstractions, that are specific to Dell EMC BMC (which is known under the name of iDRAC), to the tree of sushy Redfish resources. Example use ----------- Once installed, sushy user can access Dell EMC OEM resources. For example, OEM extension of Manager resource can be instrumental for switching the node to boot from a virtual media device: ```python import sushy root = sushy.Sushy('http://mydellemcbmc.example.com') manager = root.get_manager('iDRAC.Embedded.1') oem_manager = manager.get_oem_extension('Dell') oem_manager.set_virtual_boot_device( sushy.VIRTUAL_MEDIA_CD, persistent=False, manager=manager) ``` See full example of virtual media boot setup in the [functional test suite](https://github.com/etingof/sushy-oem-idrac/blob/master/sushy_oem_idrac/tests/functional/vmedia_boot.py). Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Description-Content-Type: text/markdown ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/README.md0000664000175000017500000000261200000000000016030 0ustar00zuulzuul00000000000000 Dell EMC OEM extension for sushy ================================ Sushy is a client [library](https://github.com/openstack/sushy) designed to communicate with [Redfish](https://en.wikipedia.org/wiki/Redfish_(specification)) based BMC. Redfish specification offers extensibility mechanism to let hardware vendors introduce their own features with the common Redfish framework. At the same time, `sushy` supports extending its data model by loading extensions found within its "oem" namespace. The `sushy-oem-idrac` package is a sushy extension package that aims at adding high-level hardware management abstractions, that are specific to Dell EMC BMC (which is known under the name of iDRAC), to the tree of sushy Redfish resources. Example use ----------- Once installed, sushy user can access Dell EMC OEM resources. For example, OEM extension of Manager resource can be instrumental for switching the node to boot from a virtual media device: ```python import sushy root = sushy.Sushy('http://mydellemcbmc.example.com') manager = root.get_manager('iDRAC.Embedded.1') oem_manager = manager.get_oem_extension('Dell') oem_manager.set_virtual_boot_device( sushy.VIRTUAL_MEDIA_CD, persistent=False, manager=manager) ``` See full example of virtual media boot setup in the [functional test suite](https://github.com/etingof/sushy-oem-idrac/blob/master/sushy_oem_idrac/tests/functional/vmedia_boot.py). ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/babel.cfg0000664000175000017500000000002100000000000016267 0ustar00zuulzuul00000000000000[python: **.py] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/requirements.txt0000664000175000017500000000045200000000000020035 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 python-dateutil>=2.7.0 # BSD sushy>=4.0.0 # Apache-2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8351398 sushy-oem-idrac-5.0.0/setup.cfg0000664000175000017500000000372500000000000016400 0ustar00zuulzuul00000000000000[metadata] name = sushy-oem-idrac summary = Dell EMC iDRAC OEM extension package for the sushy library description_file = README.md long_description_content_type = text/markdown author = OpenStack author_email = openstack-discuss@lists.openstack.org home_page = https://docs.openstack.org/sushy/latest/ classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 [files] packages = sushy_oem_idrac [entry_points] sushy.resources.manager.oems = dell = sushy_oem_idrac.resources.manager.manager:get_extension sushy.resources.storage_controller.oems = dell = sushy_oem_idrac.resources.system.storage.controller:get_extension sushy.resources.system.oems = dell = sushy_oem_idrac.resources.system.system:get_extension sushy.resources.task.oems = dell = sushy_oem_idrac.resources.taskservice.task:get_extension [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 warning-is-error = 1 [upload_sphinx] upload-dir = doc/build/html [compile_catalog] directory = sushy_oem_idrac/locale domain = sushy_oem_idrac [update_catalog] domain = sushy_oem_idrac output_dir = sushy_oem_idrac/locale input_file = sushy_oem_idrac/locale/sushy_oem_idrac.pot [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = sushy_oem_idrac/locale/sushy_oem_idrac.pot [build_releasenotes] all_files = 1 build-dir = releasenotes/build source-dir = releasenotes/source [pbr] autodoc_index_modules = True api_doc_dir = reference/api autodoc_exclude_modules = sushy_oem_idrac.tests.* [egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/setup.py0000664000175000017500000000200600000000000016260 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # 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 FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8111398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/0000775000175000017500000000000000000000000017725 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/__init__.py0000664000175000017500000000155500000000000022044 0ustar00zuulzuul00000000000000# Copyright (c) 2021-2022 Dell Inc. or its subsidiaries. # # 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. from sushy_oem_idrac.resources.manager.constants import * # noqa from sushy_oem_idrac.resources.system.constants import * # noqa from sushy_oem_idrac.resources.system.storage.constants import * # noqa from sushy_oem_idrac.resources.taskservice.constants import * # noqa ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/asynchronous.py0000664000175000017500000000504000000000000023031 0ustar00zuulzuul00000000000000# 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. from datetime import datetime from datetime import timedelta import logging import time from dateutil import parser import sushy LOG = logging.getLogger(__name__) TASK_POLL_PERIOD = 1 def _to_datetime(retry_after_str): if retry_after_str.isdigit(): # Retry-After: 120 return datetime.now() + timedelta(seconds=int(retry_after_str)) else: # Retry-After: Fri, 31 Dec 1999 23:59:59 GMT return parser.parse(retry_after_str) def http_call(conn, method, *args, **kwargs): handle = getattr(conn, method.lower()) sleep_for = kwargs.pop('sushy_task_poll_period', TASK_POLL_PERIOD) response = handle(*args, **kwargs) LOG.debug('Finished HTTP %s with args %s %s, response is ' '%d', method, args or '', kwargs, response.status_code) location = None while response.status_code == 202: location = response.headers.get('Location', location) if not location: raise sushy.exceptions.ExtensionError( error='Response %d to HTTP %s with args %s, kwargs %s ' 'does not include Location: in ' 'header' % (response.status_code, method.upper(), args, kwargs)) retry_after = response.headers.get('Retry-After') if retry_after: retry_after = _to_datetime(retry_after) sleep_for = max(0, (retry_after - datetime.now()).total_seconds()) LOG.debug('Sleeping for %d secs before retrying HTTP GET ' '%s', sleep_for, location) time.sleep(sleep_for) response = conn.get(location) LOG.debug('Finished HTTP GET %s, response is ' '%d', location, response.status_code) if response.status_code >= 400: raise sushy.exceptions.ExtensionError( error='HTTP %s with args %s, kwargs %s failed ' 'with code %s' % (method.upper(), args, kwargs, response.status_code)) return response ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/constants.py0000664000175000017500000000126200000000000022314 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. IDRAC_CONFIG_PENDING = 'LC068' IDRAC_JOB_RUNNING = 'RAC0679' NO_FOREIGN_CONFIG = 'STOR018' ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8151398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/0000775000175000017500000000000000000000000021737 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/__init__.py0000664000175000017500000000000000000000000024036 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8151398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/0000775000175000017500000000000000000000000023351 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/__init__.py0000664000175000017500000000000000000000000025450 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/constants.py0000664000175000017500000001117700000000000025746 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import enum class ExportTarget(enum.Enum): """Export system config action constants""" ALL = 'ALL' """Export entire system configuration""" BIOS = 'BIOS' """Export BIOS related configuration""" IDRAC = 'IDRAC' """Export iDRAC related configuration""" NIC = 'NIC' """Export NIC related configuration""" RAID = 'RAID' """Export RAID related configuration""" # Backward compatibility EXPORT_TARGET_ALL = ExportTarget.ALL EXPORT_TARGET_BIOS = ExportTarget.BIOS EXPORT_TARGET_IDRAC = ExportTarget.IDRAC EXPORT_TARGET_NIC = ExportTarget.NIC EXPORT_TARGET_RAID = ExportTarget.RAID class ResetType(enum.Enum): """iDRAC Reset reset type constants""" GRACEFUL = 'Graceful' """Perform a graceful shutdown followed by a restart of the system""" FORCE = 'Force' """Perform an immediate (non-graceful) shutdown, followed by a restart""" # Backward compatibility RESET_IDRAC_GRACEFUL_RESTART = ResetType.GRACEFUL RESET_IDRAC_FORCE_RESTART = ResetType.FORCE class ShutdownType(enum.Enum): """ImportSystemConfiguration ShutdownType values""" GRACEFUL = 'Graceful' """Graceful shutdown for Import System Configuration Will wait for the host up to 5 minutes to shut down before timing out. The operating system can potentially deny or ignore the graceful shutdown request. """ FORCED = 'Forced' """Forced shutdown for Import System Configuration The host server will be powered off immediately. Should be used when it is safe to power down the host. """ NO_REBOOT = 'NoReboot' """No reboot for Import System Configuration No shutdown performed. Explicit reboot is necessary to apply changes. """ # Backward compatibility IMPORT_SHUTDOWN_GRACEFUL = ShutdownType.GRACEFUL IMPORT_SHUTDOWN_FORCED = ShutdownType.FORCED IMPORT_SHUTDOWN_NO_REBOOT = ShutdownType.NO_REBOOT class ExportUse(enum.Enum): """ExportUse in ExportSystemConfiguration""" DEFAULT = 'Default' """Default export type Leaves some attributes commented out and requires user to enable them before they can be applied during import. """ CLONE = 'Clone' """Clone export type suitable for cloning a 'golden' configuration. Compared to Default export type, more attributes are enabled and storage settings adjusted to aid in cloning process. """ REPLACE = 'Replace' """Replace export type suited for replacing complete configuration. Compared to Clone export type, most attributes are enabled and storage settings adjusted to aid in the replace process. """ # Backward compatibility EXPORT_USE_DEFAULT = ExportUse.DEFAULT EXPORT_USE_CLONE = ExportUse.CLONE EXPORT_USE_REPLACE = ExportUse.REPLACE class IncludeInExport(enum.Enum): """IncludeInExport in ExportSystemConfiguration""" DEFAULT = 'Default' """Default for what to include in export. Does not include read-only attributes, and depending on Export Use, passwords are marked as ****** (for Default) or are set to default password values (for Clone and Replace). """ READ_ONLY = 'IncludeReadOnly' """Includes read-only attributes. In addition to values included by Default option, this also includes read-only attributes that cannot be changed via Import and are provided for informational purposes only. """ PASSWORD_HASHES = 'IncludePasswordHashValues' """Include password hashes. When using Clone or Replace, include password hashes, instead of default password. Can be used to replicate passwords across systems. """ READ_ONLY_PASSWORD_HASHES = ('IncludeReadOnly,IncludePasswordHashValues') """Includes both read-only attributes and password hashes. INCLUDE_EXPORT_READ_ONLY and INCLUDE_EXPORT_PASSWORD_HASHES combined """ # Backward compatibility INCLUDE_EXPORT_DEFAULT = IncludeInExport.DEFAULT INCLUDE_EXPORT_READ_ONLY = IncludeInExport.READ_ONLY INCLUDE_EXPORT_PASSWORD_HASHES = IncludeInExport.PASSWORD_HASHES INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES =\ IncludeInExport.READ_ONLY_PASSWORD_HASHES ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/idrac_card_service.py0000664000175000017500000000607000000000000027521 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy import exceptions from sushy.resources import base from sushy_oem_idrac.resources.manager import constants as mgr_cons LOG = logging.getLogger(__name__) class ForceActionField(base.CompositeField): target_uri = base.Field('target', required=True) allowed_values = base.Field('Force@Redfish.AllowableValues', adapter=list) class ActionsField(base.CompositeField): reset_idrac = ForceActionField('#DelliDRACCardService.iDRACReset') class DelliDRACCardService(base.ResourceBase): _actions = ActionsField('Actions') identity = base.Field('Id', required=True) def __init__(self, connector, identity, redfish_version=None, registries=None): """A class representing a DelliDRACCardService. :param connector: A Connector instance :param identity: The identity of the DelliDRACCardService resource :param redfish_version: The version of Redfish. Used to construct the object according to schema of the given version. :param registries: Dict of Redfish Message Registry objects to be used in any resource that needs registries to parse messages. """ super(DelliDRACCardService, self).__init__( connector, identity, redfish_version, registries) def get_allowed_reset_idrac_values(self): """Get the allowed values for resetting the idrac. :returns: A set of allowed values. """ reset_action = self._actions.reset_idrac if not reset_action.allowed_values: LOG.warning('Could not figure out the allowed values for the ' 'reset idrac action for %s', self.identity) return set(mgr_cons.ResetType) return {v for v in mgr_cons.ResetType if v.value in reset_action.allowed_values} def reset_idrac(self): """Reset the iDRAC. """ reset_type = mgr_cons.ResetType.GRACEFUL valid_resets = self.get_allowed_reset_idrac_values() if reset_type not in valid_resets: raise exceptions.InvalidParameterValueError( parameter='value', value=reset_type, valid_values=valid_resets) target_uri = self._actions.reset_idrac.target_uri payload = {"Force": reset_type.value} LOG.debug('Resetting the iDRAC %s ...', self.identity) self._conn.post(target_uri, data=payload) LOG.info('The iDRAC %s is being reset', self.identity) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/job_collection.py0000664000175000017500000000412700000000000026714 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy.resources import base LOG = logging.getLogger(__name__) class DellJobCollection(base.ResourceBase): identity = base.Field('Id', required=True) _JOB_EXPAND = '?$expand=.($levels=1)' def __init__(self, connector, identity, redfish_version=None, registries=None): """A class representing a DellJobCollection. :param connector: A Connector instance :param identity: The identity of the DellJobCollection resource :param redfish_version: The version of Redfish. Used to construct the object according to schema of the given version. :param registries: Dict of Redfish Message Registry objects to be used in any resource that needs registries to parse messages """ super(DellJobCollection, self).__init__( connector, identity, redfish_version, registries) def get_unfinished_jobs(self): """Get the unfinished jobs. :returns: A list of unfinished jobs. """ job_expand_uri = '%s%s' % (self._path, self._JOB_EXPAND) unfinished_jobs = [] LOG.debug('Getting unfinished jobs...') job_response = self._conn.get(job_expand_uri) data = job_response.json() for job in data[u'Members']: if ((job[u'JobState'] == 'Scheduled') or ( job[u'JobState'] == 'Running')): unfinished_jobs.append(job['Id']) LOG.info('Got unfinished jobs') return unfinished_jobs ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/job_service.py0000664000175000017500000000430700000000000026221 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy.resources import base from sushy.resources import common LOG = logging.getLogger(__name__) class ActionsField(base.CompositeField): delete_job_queue = common.ActionField("#DellJobService.DeleteJobQueue") class DellJobService(base.ResourceBase): _actions = ActionsField('Actions') identity = base.Field('Id', required=True) def __init__(self, connector, identity, redfish_version=None, registries=None): """A class representing a DellJobService. :param connector: A Connector instance :param identity: The identity of the DellJobService resource :param redfish_version: The version of Redfish. Used to construct the object according to schema of the given version. :param registries: Dict of Redfish Message Registry objects to be used in any resource that needs registries to parse messages. """ super(DellJobService, self).__init__( connector, identity, redfish_version, registries) def delete_jobs(self, job_ids=['JID_CLEARALL']): """Delete the given jobs, or all jobs. :param job_ids: a list of job ids to delete. Clearing all the jobs may be accomplished using the keyword JID_CLEARALL as the job_id. """ target_uri = self._actions.delete_job_queue.target_uri for job_id in job_ids: LOG.debug('Deleting the job %s', job_id) payload = {'JobID': job_id} self._conn.post(target_uri, data=payload) LOG.info('Deleted the job %s', job_id) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/lifecycle_service.py0000664000175000017500000000571600000000000027413 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy.resources import base from sushy.resources import common LOG = logging.getLogger(__name__) class ActionsField(base.CompositeField): remote_service_api_status = common.ActionField( "#DellLCService.GetRemoteServicesAPIStatus") class DellLCService(base.ResourceBase): _actions = ActionsField('Actions') _OK_STATUS_CODE = 200 _READY_STATUS = 'Ready' identity = base.Field('Id', required=True) def __init__(self, connector, identity, redfish_version=None, registries=None): """A class representing a DellLCService. :param connector: A Connector instance :param identity: The identity of the DellLCService resource :param redfish_version: The version of Redfish. Used to construct the object according to schema of the given version. :param registries: Dict of Redfish Message Registry objects to be used in any resource that needs registries to parse messages. """ super(DellLCService, self).__init__( connector, identity, redfish_version, registries) def _is_remote_service_api_status_ready(self, status_field): """Checks remote service status field :param status_field: Status field to check, e.g., LCStatus, RTStatus :returns: True if response returned and status field is Ready, otherwise False. """ target_uri = self._actions.remote_service_api_status.target_uri response = self._conn.post(target_uri, data={}) if response.status_code != self._OK_STATUS_CODE: return False data = response.json() return data[status_field] == self._READY_STATUS def is_idrac_ready(self): """Indicates if the iDRAC is ready to accept commands. :returns: A boolean value True/False based on remote service api status response. """ LOG.debug('Checking to see if the iDRAC is ready...') return self._is_remote_service_api_status_ready('LCStatus') def is_realtime_ready(self): """Indicates if real-time operations are ready to be accepted. :returns: True if ready to accept real-time operations, otherwise false. """ LOG.debug('Checking to see if the real-time operations are ready...') return self._is_remote_service_api_status_ready('RTStatus') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/manager/manager.py0000664000175000017500000006277700000000000025360 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json import logging import subprocess import time from urllib.parse import urlparse import sushy from sushy.resources import base from sushy.resources import common from sushy.resources.oem import base as oem_base from sushy.taskmonitor import TaskMonitor from sushy import utils as sushy_utils from sushy_oem_idrac import asynchronous from sushy_oem_idrac import constants from sushy_oem_idrac.resources.manager import constants as mgr_cons from sushy_oem_idrac.resources.manager import idrac_card_service from sushy_oem_idrac.resources.manager import job_collection from sushy_oem_idrac.resources.manager import job_service from sushy_oem_idrac.resources.manager import lifecycle_service from sushy_oem_idrac import utils LOG = logging.getLogger(__name__) # System Configuration Tag Constant _SYSTEM_CONFIG_TAG = "SystemConfiguration" # Response Code Constant _RESPONSE_OK_CODE = 200 # Structure {'Component FQDD': (tuple of beginning of Attribute keys)} _DESTRUCTIVE_CONF_KEYS = { 'iDRAC.Embedded.1': ('IPv4Static', 'IPv6Static', 'IPv4.1#Enable', 'IPv4.1#DHCPEnable', 'IPv6.1#Enable', 'IPv6.1#AutoConfig')} class SharedParameters(base.CompositeField): allowed_target_values = base.Field('Target@Redfish.AllowableValues') class ExportActionField(common.ActionField): shared_parameters = SharedParameters('ShareParameters') allowed_export_use_values = base.Field( 'ExportUse@Redfish.AllowableValues', adapter=list) allowed_include_in_export_values = base.Field( 'IncludeInExport@Redfish.AllowableValues', adapter=list) class ImportActionField(common.ActionField): allowed_shutdown_type_values = base.Field( 'ShutdownType@Redfish.AllowableValues', adapter=list) class DellManagerActionsField(base.CompositeField): import_system_configuration = ImportActionField( lambda key, **kwargs: key.endswith( '#OemManager.ImportSystemConfiguration')) export_system_configuration = ExportActionField( lambda key, **kwargs: key.endswith( '#OemManager.ExportSystemConfiguration')) class DellManagerExtension(oem_base.OEMResourceBase): _actions = DellManagerActionsField('Actions') ACTION_DATA = { 'ShareParameters': { 'Target': 'ALL' }, 'ImportBuffer': None } # NOTE(etingof): iDRAC job would fail if this XML has # insignificant whitespaces IDRAC_CONFIG_CD = """\ \ \ \ %s\ \ \ VCD-DVD\ \ \ \ """ IDRAC_CONFIG_FLOPPY = """\ \ \ \ %s\ \ \ VFDD\ \ \ \ """ IDRAC_MEDIA_TYPES = { sushy.VIRTUAL_MEDIA_FLOPPY: IDRAC_CONFIG_FLOPPY, sushy.VIRTUAL_MEDIA_CD: IDRAC_CONFIG_CD } RETRY_COUNT = 35 RETRY_DELAY = 15 _IDRAC_IS_READY_RETRIES = 96 _IDRAC_IS_READY_RETRY_DELAY_SEC = 10 @property def import_system_configuration_uri(self): return self._actions.import_system_configuration.target_uri @property def export_system_configuration_uri(self): return self._actions.export_system_configuration.target_uri @property @sushy_utils.cache_it def idrac_card_service(self): """Property to reference `DelliDRACCardService` instance of this manager. """ path = sushy_utils.get_sub_resource_path_by( self, ["Links", "Oem", "Dell", "DelliDRACCardService"], is_collection=False) return idrac_card_service.DelliDRACCardService( self._conn, path, self.redfish_version, self.registries) @property @sushy_utils.cache_it def lifecycle_service(self): """Property to reference `DellLCService` instance of this manager. """ path = sushy_utils.get_sub_resource_path_by( self, ["Links", "Oem", "Dell", "DellLCService"], is_collection=False) return lifecycle_service.DellLCService( self._conn, path, self.redfish_version, self.registries) @property @sushy_utils.cache_it def job_service(self): """Property to reference `DellJobService` instance of this manager. """ path = sushy_utils.get_sub_resource_path_by( self, ["Links", "Oem", "Dell", "DellJobService"], is_collection=False) return job_service.DellJobService( self._conn, path, self.redfish_version, self.registries) @property @sushy_utils.cache_it def job_collection(self): """Property to reference `DellJobService` instance of this manager. """ path = sushy_utils.get_sub_resource_path_by( self, ["Links", "Oem", "Dell", "Jobs"], is_collection=False) return job_collection.DellJobCollection( self._conn, path, self.redfish_version, self.registries) def set_virtual_boot_device(self, device, persistent=False, manager=None, system=None): """Set boot device for a node. Dell iDRAC Redfish implementation does not support setting boot device to virtual media via standard Redfish means. However, this still can be done via an OEM extension. :param device: Boot device. Values are vendor-specific. :param persistent: Whether to set next-boot, or make the change permanent. Default: False. :param manager: Manager of OEM extension. Optional. :param system: System of OEM extension. Optional. :raises: InvalidParameterValue if Dell OEM extension can't be used. :raises: ExtensionError on failure to perform requested operation. """ try: idrac_media = self.IDRAC_MEDIA_TYPES[device] except KeyError: raise sushy.exceptions.InvalidParameterValue( error='Unknown or unsupported device %s' % device) idrac_media = idrac_media % ( manager.identity if manager else self._parent_resource.identity, 'Disabled' if persistent else 'Enabled') action_data = dict(self.ACTION_DATA, ImportBuffer=idrac_media) # TODO(etingof): figure out if on-time or persistent boot can at # all be implemented via this OEM call attempts = self.RETRY_COUNT rebooted = False while True: try: response = asynchronous.http_call( self._conn, 'post', self.import_system_configuration_uri, data=action_data, sushy_task_poll_period=1) LOG.info("Set boot device to %(device)s via " "Dell OEM magic spell (%(retries)d " "retries)", {'device': device, 'retries': self.RETRY_COUNT - attempts}) return response except (sushy.exceptions.ServerSideError, sushy.exceptions.BadRequestError) as exc: LOG.warning( 'Dell OEM set boot device failed (attempts left ' '%d): %s', attempts, exc) errors = exc.body and exc.body.get( '@Message.ExtendedInfo') or [] for error in errors: message_id = error.get('MessageId') LOG.warning('iDRAC error: %s', error.get('Message', 'Unknown error')) if constants.IDRAC_CONFIG_PENDING in message_id: if not rebooted: LOG.warning( 'Let\'s try to turn it off and on again... ' 'This may consume one-time boot settings if ' 'set previously!') utils.reboot_system(system) rebooted = True break elif constants.IDRAC_JOB_RUNNING in message_id: pass else: time.sleep(self.RETRY_DELAY) if not attempts: LOG.error('Too many (%d) retries, bailing ' 'out.', self.RETRY_COUNT) raise attempts -= 1 def get_allowed_export_target_values(self): """Get the allowed targets of export system configuration. :returns: A set of allowed values. """ export_action = self._actions.export_system_configuration allowed_values = export_action.shared_parameters.allowed_target_values if not allowed_values: LOG.warning('Could not figure out the allowed values for the ' 'target of export system configuration at %s', self.path) return set(mgr_cons.ExportTarget) return {v for v in mgr_cons.ExportTarget if v.value in allowed_values} def get_allowed_export_use_values(self): """Get allowed export use values of export system configuration. :returns: A set of allowed export use values. """ export_action = self._actions.export_system_configuration allowed_values = export_action.allowed_export_use_values if not allowed_values: LOG.warning('Could not figure out the allowed values for the ' 'export use of export system configuration at %s', self.path) return set(mgr_cons.ExportUse) return {v for v in mgr_cons.ExportUse if v.value in allowed_values} def get_allowed_include_in_export_values(self): """Get allowed include in export values of export system configuration. :returns: A set of allowed include in export values. """ export_action = self._actions.export_system_configuration allowed_values = export_action.allowed_include_in_export_values if not allowed_values: LOG.warning('Could not figure out the allowed values for the ' 'include in export of export system configuration at ' '%s', self.path) return set(mgr_cons.IncludeInExport) return {v for v in mgr_cons.IncludeInExport if v.value in allowed_values} def _export_system_configuration( self, target, export_use=mgr_cons.ExportUse.DEFAULT, include_in_export=mgr_cons.IncludeInExport.DEFAULT): """Export system configuration. It exports system configuration for specified target like NIC, BIOS, RAID and allows to configure purpose for export and what to include. :param target: Component of the system to export the configuration from. Can be the entire system. Valid values can be gotten from `get_allowed_export_system_config_values`. :param export_use: Export use. Optional, defaults to "Default". Valid values can be gotten from `get_allowed_export_use_values`. :param include_in_export: What to include in export. Optional. Defaults to "Default". Valid values can be gotten from `get_allowed_include_in_export_values`. :returns: Response object containing configuration details. :raises: InvalidParameterValueError on invalid target. :raises: ExtensionError on failure to perform requested operation """ valid_allowed_targets = self.get_allowed_export_target_values() if target not in valid_allowed_targets: raise sushy.exceptions.InvalidParameterValueError( parameter='target', value=target, valid_values=valid_allowed_targets) allowed_export_use = self.get_allowed_export_use_values() if export_use not in allowed_export_use: raise sushy.exceptions.InvalidParameterValueError( parameter='export_use', value=export_use, valid_values=allowed_export_use) allowed_include_in_export = self.get_allowed_include_in_export_values() if include_in_export not in allowed_include_in_export: # Check if value contains comma and validate each item separately # Older iDRACs used to include comma separated option in # AllowableValues but got removed in newer versions violating # AllowableValues validation logic. all_items_valid = True if not isinstance(include_in_export, mgr_cons.IncludeInExport): all_items_valid = False else: items = include_in_export.value.split(',') for item in items: if (mgr_cons.IncludeInExport(item) not in allowed_include_in_export): all_items_valid = False break if not all_items_valid: raise sushy.exceptions.InvalidParameterValueError( parameter='include_in_export', value=include_in_export, valid_values=allowed_include_in_export) target = mgr_cons.ExportTarget(target).value export_use = mgr_cons.ExportUse(export_use).value include_in_export = mgr_cons.IncludeInExport(include_in_export).value action_data = { 'ShareParameters': { 'Target': target }, 'ExportFormat': "JSON", 'ExportUse': export_use, 'IncludeInExport': include_in_export } try: response = asynchronous.http_call( self._conn, 'post', self.export_system_configuration_uri, data=action_data) LOG.info("Successfully exported system configuration " "for %(target)s", {'target': target}) return response except (sushy.exceptions.ExtensionError, sushy.exceptions.InvalidParameterValueError) as exc: LOG.error('Dell OEM export system configuration failed : %s', exc) raise def export_system_configuration(self, include_destructive_fields=True): """Export system configuration. Exports ALL targets for cloning and includes password hashes and read-only attributes. :param include_destructive_fields: Whether includes settings such as iDRAC static IP address that could lead to losing access to iDRAC if importing this configuration into another system. Default to True for backward compability. False recommended if unsure. :returns: Response object containing configuration details. :raises: InvalidParameterValueError on invalid target. :raises: ExtensionError on failure to perform requested operation """ include_in_export = mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES response = self._export_system_configuration( mgr_cons.ExportTarget.ALL, export_use=mgr_cons.ExportUse.CLONE, include_in_export=include_in_export) if (response.status_code == _RESPONSE_OK_CODE and not include_destructive_fields): conf = response.json() if _SYSTEM_CONFIG_TAG in conf.keys(): for fqdd, values in _DESTRUCTIVE_CONF_KEYS.items(): for comp in conf[_SYSTEM_CONFIG_TAG]['Components']: if comp['FQDD'] == fqdd: attributes_copy = comp['Attributes'].copy() for child in comp['Attributes']: if child.get('Name').startswith(values): attributes_copy.remove(child) comp['Attributes'] = attributes_copy response._content = json.dumps(conf).encode() return response def get_pxe_port_macs_bios(self, ethernet_interfaces_mac): """Get a list of pxe port MAC addresses for BIOS. :param ethernet_interfaces_mac: Dictionary of ethernet interfaces. :returns: List of pxe port MAC addresses. :raises: ExtensionError on failure to perform requested operation. """ pxe_port_macs = [] # Get NIC configuration nic_settings = self._export_system_configuration( target=mgr_cons.ExportTarget.NIC) if nic_settings.status_code != _RESPONSE_OK_CODE: error = (('An error occurred when attempting to export ' 'the system configuration. Status code: %(code), ' 'Error details: %(err)'), {'code': nic_settings.status_code, 'err': nic_settings.__dict__}) LOG.error(error) raise sushy.exceptions.ExtensionError(error=error) # Parse the exported system configuration for the NIC # ports that are set to PXE boot json_data = nic_settings.json() if _SYSTEM_CONFIG_TAG in json_data.keys(): for root in json_data[_SYSTEM_CONFIG_TAG]['Components']: nic_id = root['FQDD'] for child in root['Attributes']: if child.get('Name') == "LegacyBootProto": if child['Value'] == "PXE": mac_address = ethernet_interfaces_mac[nic_id] pxe_port_macs.append(mac_address) return pxe_port_macs else: error = (('Failed to get system configuration from response')) LOG.error(error) raise sushy.exceptions.ExtensionError(error=error) def get_allowed_import_shutdown_type_values(self): """Get the allowed shutdown types of import system configuration. :returns: A set of allowed shutdown type values. """ import_action = self._actions.import_system_configuration allowed_values = import_action.allowed_shutdown_type_values if not allowed_values: LOG.warning('Could not figure out the allowed values for the ' 'shutdown type of import system configuration at %s', self.path) return set(mgr_cons.ShutdownType) return {v for v in mgr_cons.ShutdownType if v.value in allowed_values} def import_system_configuration(self, import_buffer): """Imports system configuration. Caller needs to handle system reboot separately. :param import_buffer: Configuration data to be imported. :returns: Task monitor instance to watch for task completion """ action_data = dict(self.ACTION_DATA, ImportBuffer=import_buffer) # Caller needs to handle system reboot separately to preserve # one-time boot settings. shutdown_type = mgr_cons.ShutdownType.NO_REBOOT allowed_shutdown_types = self.get_allowed_import_shutdown_type_values() if shutdown_type not in allowed_shutdown_types: raise sushy.exceptions.InvalidParameterValueError( parameter='shutdown_type', value=shutdown_type, valid_values=allowed_shutdown_types) action_data['ShutdownType'] = shutdown_type.value response = self._conn.post(self.import_system_configuration_uri, data=action_data) return TaskMonitor.from_response( self._conn, response, self.import_system_configuration_uri) def reset_idrac(self, wait=True, ready_wait_time=60): """Reset the iDRAC and wait for it to become ready. :param wait: Whether to return immediately or wait for iDRAC to become operational. :param ready_wait_time: Amount of time in seconds to wait before starting to check on the iDRAC's status. """ self.idrac_card_service.reset_idrac() if not wait: return host = urlparse(self._conn._url).netloc LOG.debug("iDRAC %(host)s was reset, " "waiting for return to operational state", {'host': host}) self._wait_for_idrac(host, ready_wait_time) self._wait_until_idrac_is_ready(host, self._IDRAC_IS_READY_RETRIES, self._IDRAC_IS_READY_RETRY_DELAY_SEC) def _wait_for_idrac_state(self, host, alive=True, ping_count=3, retries=24): """Wait for iDRAC to become pingable or not pingable. :param host: Hostname or IP of the iDRAC interface. :param alive: True for pingable state and False for not pingable state. :param ping_count: Number of consecutive ping results, per 'alive', for success. :param retries: Number of ping retries. :returns: True on reaching specified host ping state; otherwise, False. """ if alive: ping_type = "pingable" else: ping_type = "not pingable" LOG.debug("Waiting for iDRAC %(host)s to become %(ping_type)s", {'host': host, 'ping_type': ping_type}) response_count = 0 while retries > 0: response = self._ping_host(host) retries -= 1 if response == alive: response_count += 1 LOG.debug("iDRAC %(host)s is %(ping_type)s, " "count=%(response_count)s", {'host': host, 'ping_type': ping_type, 'response_count': response_count}) if response_count == ping_count: LOG.debug("Reached specified %(alive)s count for iDRAC " "%(host)s", {'alive': alive, 'host': host}) return True else: response_count = 0 if alive: LOG.debug("iDRAC %(host)s is still not pingable", {'host': host}) else: LOG.debug("iDRAC %(host)s is still pingable", {'host': host}) time.sleep(10) return False def _wait_for_idrac(self, host, post_pingable_wait_time): """Wait for iDRAC to transition from unpingable to pingable. :param host: Hostname or IP of the iDRAC interface. :param post_pingable_wait_time: Amount of time in seconds to wait after the host becomes pingable. :raises: ExtensionError on failure to perform requested operation. """ state_reached = self._wait_for_idrac_state( host, alive=False, ping_count=2, retries=24) if not state_reached: error_msg = ("Timed out waiting iDRAC %(host)s to become not " "pingable", {'host': host}) LOG.error(error_msg) raise sushy.exceptions.ExtensionError(error=error_msg) LOG.debug("iDRAC %(host)s has become not pingable", {'host': host}) state_reached = self._wait_for_idrac_state(host, alive=True, ping_count=3, retries=24) if not state_reached: error_msg = ("Timed out waiting iDRAC %(host)s to become pingable", {'host': host}) LOG.error(error_msg) raise sushy.exceptions.ExtensionError(error=error_msg) LOG.debug("iDRAC %(host)s has become pingable", {'host': host}) time.sleep(post_pingable_wait_time) def _wait_until_idrac_is_ready(self, host, retries, retry_delay): """Wait until the iDRAC is in a ready state. :param host: Hostname or IP of the iDRAC interface. :param retries: The number of times to check if the iDRAC is ready. :param retry_delay: The number of seconds to wait between retries. :raises: ExtensionError on failure to perform requested operation. """ while retries > 0: LOG.debug("Checking to see if iDRAC %(host)s is ready", {'host': host}) if self.lifecycle_service.is_idrac_ready(): LOG.debug("iDRAC %(host)s is ready", {'host': host}) return LOG.debug("iDRAC %(host)s is not ready", {'host': host}) retries -= 1 if retries > 0: time.sleep(retry_delay) if retries == 0: error_msg = ("Timed out waiting iDRAC %(host)s to become " "ready after reset", {'host': host}) LOG.error(error_msg) raise sushy.exceptions.ExtensionError(error=error_msg) def _ping_host(self, host): """Ping the hostname or IP of a host. :param host: Hostname or IP. :returns: True if host is alive; otherwise, False. """ response = subprocess.call(["ping", "-c", "1", host]) return response == 0 def get_extension(*args, **kwargs): return DellManagerExtension ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8191397 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/0000775000175000017500000000000000000000000023263 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/constants.py0000664000175000017500000000173300000000000025655 0ustar00zuulzuul00000000000000# Copyright (c) 2021-2022 Dell Inc. or its subsidiaries. # # 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. import enum class PhysicalDiskStateMode(enum.Enum): """Physical disk state mode constants""" RAID = 'RAID' """RAID physical disk state mode""" NONRAID = 'Non-RAID' """Non-RAID physical disk state mode""" # For backward compatibility PHYSICAL_DISK_STATE_MODE_RAID = PhysicalDiskStateMode.RAID PHYSICAL_DISK_STATE_MODE_NONRAID = PhysicalDiskStateMode.NONRAID ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/raid_service.py0000664000175000017500000001305000000000000026273 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy import exceptions from sushy.resources import base from sushy.resources import common from sushy import taskmonitor from sushy_oem_idrac import constants LOG = logging.getLogger(__name__) class ActionsField(base.CompositeField): convert_to_raid = common.ActionField("#DellRaidService.ConvertToRAID") convert_to_nonraid = common.ActionField( "#DellRaidService.ConvertToNonRAID") clear_foreign_config = common.ActionField( "#DellRaidService.ClearForeignConfig") class DellRaidService(base.ResourceBase): identity = base.Field('Id', required=True) _actions = ActionsField('Actions') def __init__(self, connector, identity, redfish_version=None, registries=None, root=None): """A class representing a DellRaidService. :param connector: A Connector instance :param identity: The identity of the DellRaidService resource :param redfish_version: The version of Redfish. Used to construct the object according to schema of the given version. :param registries: Dict of Redfish Message Registry objects to be used in any resource that needs registries to parse messages. :param root: Sushy root object. Empty for Sushy root itself. """ super(DellRaidService, self).__init__( connector, identity, redfish_version=redfish_version, registries=registries, root=root) def convert_to_raid(self, physical_disk_fqdds): """Converts physical disks to a state usable for RAID :param physical_disk_fqdds: An array of FQDDs where each identifies a physical drive. :returns: Sushy's TaskMonitor instance for TaskService task """ target_uri = self._actions.convert_to_raid.target_uri payload = {'PDArray': physical_disk_fqdds} response = self._conn.post(target_uri, data=payload) task_monitor = self._get_task_monitor_from_dell_job(response) LOG.info('Converting to RAID mode: %s', physical_disk_fqdds) return task_monitor def convert_to_nonraid(self, physical_disk_fqdds): """Converts physical disks to non-RAID state. :param physical_disk_fqdds: An array of FQDDs where each identifies a physical drive. :returns: Sushy's TaskMonitor instance for TaskService task """ target_uri = self._actions.convert_to_nonraid.target_uri payload = {'PDArray': physical_disk_fqdds} response = self._conn.post(target_uri, data=payload) task_monitor = self._get_task_monitor_from_dell_job(response) LOG.info('Converting to non-RAID mode: %s', physical_disk_fqdds) return task_monitor def clear_foreign_config(self, controller_fqdd): """Clears foreign configuration Prepares any foreign physical disks for inclusion in the local configuration :param controller_fqdd: FQDD of controller to clear foreign config :returns: Sushy's TaskMonitor instance for TaskService task if there are foreign drives to clear, otherwise None. """ target_uri = self._actions.clear_foreign_config.target_uri payload = {'TargetFQDD': controller_fqdd} try: response = self._conn.post(target_uri, data=payload) except exceptions.BadRequestError as ex: # Check if failed for no foreign drives errors = ex.body and ex.body.get('@Message.ExtendedInfo') or [] no_foreign_conf = [x for x in errors if constants.NO_FOREIGN_CONFIG in x.get('MessageId')] if len(no_foreign_conf) == 0: raise ex else: LOG.debug('%s: %s', no_foreign_conf[0].get('Message'), controller_fqdd) return task_mon = self._get_task_monitor_from_dell_job(response) LOG.info('Clearing foreign config: %s', controller_fqdd) return task_mon def _get_task_monitor_from_dell_job(self, response): """From OEM job response returns generic Task monitor :param response: Response from OEM job :returns: Sushy's TaskMonitor instance for TaskService task """ location = response.headers.get('Location') if not location: raise exceptions.ExtensionError( error='Response %s does not include Location in header' % (response.url)) task_id = location.split('/')[-1] task = None for t in self.root.get_task_service().tasks.get_members(): if t.identity == task_id: task = t break if not task: raise exceptions.ExtensionError( error="Did not find task by id %s" % task_id) return taskmonitor.TaskMonitor( self._conn, task.path, redfish_version=self.redfish_version, registries=self.registries) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8191397 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/storage/0000775000175000017500000000000000000000000024727 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/storage/constants.py0000664000175000017500000000162200000000000027316 0ustar00zuulzuul00000000000000# Copyright (c) 2022 Dell Inc. or its subsidiaries. # # 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. import enum class ControllerMode(enum.Enum): """RAID controller modes.""" RAID = "RAID" """RAID mode.""" HBA = "HBA" """HBA/Passthru mode. Does not support RAID. For PERC 9 controllers.""" EHBA = "EnhancedHBA" """Enhanced HBA mode. Limited RAID support. For PERC 10 controllers.""" ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/storage/controller.py0000664000175000017500000000417600000000000027474 0ustar00zuulzuul00000000000000# Copyright (c) 2022 Dell Inc. or its subsidiaries. # # 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. import sushy from sushy.resources import base from sushy.resources.oem import base as oem_base from sushy_oem_idrac.resources.system.storage import constants as s_cons class DellStorageController(base.CompositeField): controller_mode = base.MappedField('ControllerMode', s_cons.ControllerMode) """Mode of RAID controller""" class DellStorageControllerExtension(oem_base.OEMResourceBase): dell_storage_controller = DellStorageController('DellStorageController') def convert_to_raid(self): """Converts to RAID mode if applicable If PERC 9 or PERC 10 controller is in non-RAID mode, then convert to RAID mode. No changes made for PERC 11 and above as they support only RAID mode, and BOSS controller as it does not have controller mode. :returns: TaskMonitor if controller mode changes applied and need to reboot, otherwise None """ controller_mode = self.dell_storage_controller.controller_mode # BOSS will have this empty, PERC will have something assigned if controller_mode and controller_mode != s_cons.ControllerMode.RAID: patch = { "Oem": { "Dell": { "DellStorageController": { "ControllerMode": s_cons.ControllerMode.RAID.value}}}} return self._parent_resource.update( patch, apply_time=sushy.ApplyTime.ON_RESET) def get_extension(*args, **kwargs): return DellStorageControllerExtension ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/system/system.py0000664000175000017500000001442700000000000025171 0ustar00zuulzuul00000000000000# Copyright (c) 2021-2022 Dell Inc. or its subsidiaries. # # 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. import sushy from sushy import exceptions from sushy.resources.oem import base as oem_base from sushy import utils as sushy_utils from sushy_oem_idrac.resources.system import constants as sys_cons from sushy_oem_idrac.resources.system import raid_service def _filter_disks_not_in_mode(controller_to_disks, mode): """Filters disks that are not in requested mode :param controller_to_disks: dictionary of controllers and their drives :param mode: constants.PhysicalDiskStateMode :returns: dictionary of controllers and their drives that need mode changed """ sushy_raw_device = sushy.VOLUME_TYPE_RAW_DEVICE for controller, drives in controller_to_disks.items(): toprocess_drives = [] for drive in drives: is_raw_device = False volumes = None try: volumes = drive.volumes except exceptions.MissingAttributeError: pass if (volumes and (volumes[0].volume_type == sushy_raw_device or volumes[0].raid_type is None)): is_raw_device = True if (mode == sys_cons.PhysicalDiskStateMode.RAID and is_raw_device or mode == sys_cons.PhysicalDiskStateMode.NONRAID and not is_raw_device): toprocess_drives.append(drive) controller_to_disks[controller] = toprocess_drives return controller_to_disks class DellSystemExtension(oem_base.OEMResourceBase): @property @sushy_utils.cache_it def raid_service(self): """`DellRaidService` of the system""" path = sushy_utils.get_sub_resource_path_by( self, ["Links", "Oem", "Dell", "DellRaidService"], is_collection=False) return raid_service.DellRaidService( self._conn, path, redfish_version=self.redfish_version, registries=self.registries, root=self.root) def change_physical_disk_state(self, mode, controller_to_disks=None): """Converts physical disks RAID status Converts only those disks that are not already in requested mode. :param mode: constants.PhysicalDiskStateMode :param controller_to_disks: dictionary of controllers and their drives. Optional, if not provided, processes all RAID, except BOSS, controller drives. :returns: List of task monitors for each controller's disks if any drives need changes """ if not controller_to_disks: controller_to_disks = self._get_controller_to_disks() # Do not process BOSS controllers as can't convert their disks boss_controllers = [c for c in controller_to_disks if 'BOSS' in c.name.upper()] for c in boss_controllers: controller_to_disks.pop(c) controller_to_disks = _filter_disks_not_in_mode( controller_to_disks, mode) # Convert by each controller that have eligible disks task_monitors = [] for controller, drives in controller_to_disks.items(): if drives: drive_fqdds = [d.identity for d in drives] if mode == sys_cons.PhysicalDiskStateMode.RAID: task_monitors.append( self.raid_service.convert_to_raid(drive_fqdds)) elif mode == sys_cons.PhysicalDiskStateMode.NONRAID: task_monitors.append( self.raid_service.convert_to_nonraid(drive_fqdds)) return task_monitors def clear_foreign_config(self, storage_list=None): """Clears foreign config on given controllers :param storage_list: List of storage objects, each of which corresponds to a controller :returns: List of task monitors, where each entry is for a controller that has foreign config to clear """ if storage_list is None: storage_list = self._get_storage_list() # Do not process BOSS controllers as not supporting clearing boss_storage = [s for s in storage_list if any(c for c in s.storage_controllers if 'BOSS' in c.name.upper())] for s in boss_storage: storage_list.remove(s) task_monitors = [] for storage in storage_list: task_mon = self.raid_service.clear_foreign_config(storage.identity) if task_mon: task_monitors.append(task_mon) return task_monitors def _get_controller_to_disks(self): """Gets all RAID controllers and their disks on system :returns: dictionary of RAID controllers and their disks """ controller_to_disks = {} for storage in self._parent_resource.storage.get_members(): controller = (storage.storage_controllers[0] if storage.storage_controllers else None) if not controller or controller and not controller.raid_types: continue controller_to_disks[controller] = storage.drives return controller_to_disks def _get_storage_list(self): """Gets all storage items corresponding to RAID controllers :returns: list of storage items """ storage_list = [] for storage in self._parent_resource.storage.get_members(): controller = (storage.storage_controllers[0] if storage.storage_controllers else None) if not controller or controller and not controller.raid_types: continue storage_list.append(storage) return storage_list def get_extension(*args, **kwargs): return DellSystemExtension ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8191397 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/taskservice/0000775000175000017500000000000000000000000024262 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/taskservice/constants.py0000664000175000017500000001655300000000000026662 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. import enum class JobState(enum.Enum): """Job state constants""" COMPLETED = "Completed" """A job is in completed state""" COMPLETED_ERRORS = "CompletedWithErrors" """A job is in completed state with errors""" DOWNLOADED = "Downloaded" """A job is in downloaded state""" DOWNLOADING = "Downloading" """A job is in downloading state""" FAILED = "Failed" """A job is in failed state""" NEW = "New" """A job is in newly created state""" PAUSED = "Paused" """A job is in paused state""" PENDING_ACTIVATION = "PendingActivation" """A job is in pending activation state""" READY_EXECUTION = "ReadyForExecution" """A job is in ready for execution state""" REBOOT_COMPLETED = "RebootCompleted" """A job is in reboot completed state""" REBOOT_FAILED = "RebootFailed" """A job is in reboot failed state""" REBOOT_PENDING = "RebootPending" """A job is in pending state for reboot""" RUNNING = "Running" """A job is in running state""" SCHEDULED = "Scheduled" """A job is in scheduled state""" SCHEDULING = "Scheduling" """A job is in scheduling state""" UNKNOWN = "Unknown" """A job is in unknown state""" WAITING = "Waiting" """A job is in waiting state""" # Backward compatibility JOB_STATE_COMPLETED = JobState.COMPLETED JOB_STATE_COMPLETED_ERRORS = JobState.COMPLETED_ERRORS JOB_STATE_DOWNLOADED = JobState.DOWNLOADED JOB_STATE_DOWNLOADING = JobState.DOWNLOADING JOB_STATE_FAILED = JobState.FAILED JOB_STATE_NEW = JobState.NEW JOB_STATE_PAUSED = JobState.PAUSED JOB_STATE_PENDING_ACTIVATION = JobState.PENDING_ACTIVATION JOB_STATE_READY_EXECUTION = JobState.READY_EXECUTION JOB_STATE_REBOOT_COMPLETED = JobState.REBOOT_COMPLETED JOB_STATE_REBOOT_FAILED = JobState.REBOOT_FAILED JOB_STATE_REBOOT_PENDING = JobState.REBOOT_PENDING JOB_STATE_RUNNING = JobState.RUNNING JOB_STATE_SCHEDULED = JobState.SCHEDULED JOB_STATE_SCHEDULING = JobState.SCHEDULING JOB_STATE_UNKNOWN = JobState.UNKNOWN JOB_STATE_WAITING = JobState.WAITING class JobType(enum.Enum): """Job type constants""" BIOS_CONF = "BIOSConfiguration" """A BIOS configuration job""" EXPORT_CONF = "ExportConfiguration" """A server configuration profile export job""" FC_CONF = "FCConfiguration" """A Fibre Channel configuration job""" FACTORY_CONF_EXPORT = "FactoryConfigurationExport" """A factory configuration export job""" FIRMWARE_ROLLBACK = "FirmwareRollback" """A firmware rollback job""" FIRMWARE_UPDATE = "FirmwareUpdate" """A firmware update job""" HW_INVENTORY_EXPORT = "HardwareInventoryExport" """A hardware inventory export job""" IMPORT_CONF = "ImportConfiguration" """A server configuration profile import job""" INBAND_BIOS_CONF = "InbandBIOSConfiguration" """An inband BIOS configuration job""" LC_CONF = "LCConfig" """A lifecycle controller attribute configuration job""" LC_EXPORT = "LCExport" """A lifecycle controller export job""" LC_LOG_EXPORT = "LCLogExport" """A lifecycle controller log export job""" LICENSE_EXPORT = "LicenseExport" """A license export job""" LICENSE_IMPORT = "LicenseImport" """A license import job""" MSG_REG_EXPORT = "MessageRegistryExport" """Export message registry report job""" NIC_CONF = "NICConfiguration" """A NIC configuration job""" OS_DEPLOY = "OSDeploy" """Operating System deploy job""" RAID_CONF = "RAIDConfiguration" """A RAID configuration job""" RT_NO_REBOOT_CONF = "RealTimeNoRebootConfiguration" """A real time configuration job without reboot""" REBOOT_FORCE = "RebootForce" """A reboot job with forced shutdown""" REBOOT_NO_FORCE = "RebootNoForce" """A graceful reboot job without forced shutdown""" REBOOT_POWER_CYCLE = "RebootPowerCycle" """A power cycle job""" REMOTE_DIAG = "RemoteDiagnostics" """A remote diagnostics job""" REPO_UPDATE = "RepositoryUpdate" """An update job from a repository""" SA_COL_EXP_HEALTH_DATA = "SACollectExportHealthData" """Support Assist collect and export health data job""" SA_COL_HEALTH_DATA = "SACollectHealthData" """Support Assist collect health data job""" SA_EXP_HEALTH_DATA = "SAExportHealthData" """Support Assist export health data job""" SA_ISM = "SAExposeISM" """Support Assist expose ISM installer package to host job""" SA_REG = "SARegistration" """Support Assist register iDRAC to Dell backend server job""" SEKM_REKEY = "SEKMRekey" """A Secure Enterprise Key Manager rekey job""" SEKM_STATUS_SET = "SEKMStatusSet" """A Secure Enterprise Key Manager status set job""" SHUTDOWN = "Shutdown" """A shutdown job""" SYS_ERASE = "SystemErase" """A selective system erase job""" SYS_INFO_CONF = "SystemInfoConfiguration" """A system info configuration job""" THERMAL_HIST_EXP = "ThermalHistoryExport" """A thermal history export job""" UNKNOWN = "Unknown" """An unknown job""" IDRAC_CONF = "iDRACConfiguration" """An iDRAC configuration job""" # Backward compatibility JOB_TYPE_BIOS_CONF = JobType.BIOS_CONF JOB_TYPE_EXPORT_CONF = JobType.EXPORT_CONF JOB_TYPE_FC_CONF = JobType.FC_CONF JOB_TYPE_FACTORY_CONF_EXPORT = JobType.FACTORY_CONF_EXPORT JOB_TYPE_FIRMWARE_ROLLBACK = JobType.FIRMWARE_ROLLBACK JOB_TYPE_FIRMWARE_UPDATE = JobType.FIRMWARE_UPDATE JOB_TYPE_HW_INVENTORY_EXPORT = JobType.HW_INVENTORY_EXPORT JOB_TYPE_IMPORT_CONF = JobType.IMPORT_CONF JOB_TYPE_INBAND_BIOS_CONF = JobType.INBAND_BIOS_CONF JOB_TYPE_LC_CONF = JobType.LC_CONF JOB_TYPE_LC_EXPORT = JobType.LC_EXPORT JOB_TYPE_LC_LOG_EXPORT = JobType.LC_LOG_EXPORT JOB_TYPE_LICENSE_EXPORT = JobType.LICENSE_EXPORT JOB_TYPE_LICENSE_IMPORT = JobType.LICENSE_IMPORT JOB_TYPE_MSG_REG_EXPORT = JobType.MSG_REG_EXPORT JOB_TYPE_NIC_CONF = JobType.NIC_CONF JOB_TYPE_OS_DEPLOY = JobType.OS_DEPLOY JOB_TYPE_RAID_CONF = JobType.RAID_CONF JOB_TYPE_RT_NO_REBOOT_CONF = JobType.RT_NO_REBOOT_CONF JOB_TYPE_REBOOT_FORCE = JobType.REBOOT_FORCE JOB_TYPE_REBOOT_NO_FORCE = JobType.REBOOT_NO_FORCE JOB_TYPE_REBOOT_POWER_CYCLE = JobType.REBOOT_POWER_CYCLE JOB_TYPE_REMOTE_DIAG = JobType.REMOTE_DIAG JOB_TYPE_REPO_UPDATE = JobType.REPO_UPDATE JOB_TYPE_SA_COL_EXP_HEALTH_DATA = JobType.SA_COL_EXP_HEALTH_DATA JOB_TYPE_SA_COL_HEALTH_DATA = JobType.SA_COL_HEALTH_DATA JOB_TYPE_SA_EXP_HEALTH_DATA = JobType.SA_EXP_HEALTH_DATA JOB_TYPE_SA_ISM = JobType.SA_ISM JOB_TYPE_SA_REG = JobType.SA_REG JOB_TYPE_SEKM_REKEY = JobType.SEKM_REKEY JOB_TYPE_SEKM_STATUS_SET = JobType.SEKM_STATUS_SET JOB_TYPE_SHUTDOWN = JobType.SHUTDOWN JOB_TYPE_SYS_ERASE = JobType.SYS_ERASE JOB_TYPE_SYS_INFO_CONF = JobType.SYS_INFO_CONF JOB_TYPE_THERMAL_HIST_EXP = JobType.THERMAL_HIST_EXP JOB_TYPE_UNKNOWN = JobType.UNKNOWN JOB_TYPE_IDRAC_CONF = JobType.IDRAC_CONF ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/resources/taskservice/task.py0000664000175000017500000000430000000000000025573 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. import logging from sushy.resources import base from sushy.resources.oem import base as oem_base from sushy_oem_idrac.resources.taskservice import constants as ts_cons LOG = logging.getLogger(__name__) class DellTaskExtension(oem_base.OEMResourceBase): """Dell OEM extension for DellJob type""" identity = base.Field('Id', required=True) name = base.Field('Name', required=True) description = base.Field('Description') completion_time = base.Field('CompletionTime') """Job completion time""" end_time = base.Field('EndTime') """End time of job Timestamp until when the service will wait for a job to complete. If a job does not complete within this time, it is killed and marked as failed. TIME_NA is a default value and implies EndTime is not applicable. """ job_state = base.MappedField('JobState', ts_cons.JobState) """Job state""" job_type = base.MappedField('JobType', ts_cons.JobType) """Job type""" message = base.Field('Message') """The status message for job""" message_args = base.Field('MessageArgs') """Array of message arguments for message field""" message_id = base.Field('MessageId') """Message id for job""" percent_complete = base.Field('PercentComplete', adapter=int) """The percentage completion of job""" start_time = base.Field('StartTime') """Scheduled start time of job String that will contain a timestamp in Edm.DateTime format. TIME_NOW is a default value and implies apply pending configuration now. """ def get_extension(*args, **kwargs): return DellTaskExtension ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8191397 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/0000775000175000017500000000000000000000000021067 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/__init__.py0000664000175000017500000000000000000000000023166 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8191397 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/functional/0000775000175000017500000000000000000000000023231 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/functional/__init__.py0000664000175000017500000000000000000000000025330 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/functional/vmedia_boot.py0000664000175000017500000000630000000000000026072 0ustar00zuulzuul00000000000000# 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. import logging import os import sys import sushy from sushy_oem_idrac import utils USERNAME = 'root' PASSWORD = 'calvin' SERVICE_ROOT = 'http://demo.snmplabs.com:80/redfish/v1' SYSTEM_ID = '437XR1138R2' BOOT_DEVICE = sushy.VIRTUAL_MEDIA_CD BOOT_MODE = sushy.BOOT_SOURCE_MODE_BIOS BOOT_IMAGE = 'http://demo.snmplabs.com/mini.iso' LOG = logging.getLogger(__name__) def main(): """Boot Dell node from virtual media device""" LOG.setLevel(logging.INFO) handler = logging.StreamHandler() handler.setLevel(logging.INFO) LOG.addHandler(handler) authenticator = sushy.auth.BasicAuth(USERNAME, PASSWORD) conn = sushy.Sushy(SERVICE_ROOT, verify=False, auth=authenticator) LOG.info('connected to %s', SERVICE_ROOT) system = conn.get_system( os.path.join(SERVICE_ROOT, 'Systems', SYSTEM_ID)) LOG.info('read system resource %s', system.identity) for manager in system.managers: LOG.info('trying manager %s', manager.identity) for v_media in manager.virtual_media.get_members(): if BOOT_DEVICE not in v_media.media_types: continue LOG.info( 'device %s is present at %s', BOOT_DEVICE, manager.identity) try: manager_oem = manager.get_oem_extension('Dell') except sushy.exceptions.OEMExtensionNotFoundError: LOG.info('Dell OEM not found') continue LOG.info('found Dell OEM extension at %s', manager.identity) if v_media.inserted: v_media.eject_media() LOG.info('ejected virtual media') v_media.insert_media(BOOT_IMAGE, inserted=True, write_protected=True) LOG.info('inserted boot image %s into virtual media', BOOT_IMAGE) # the caller (e.g. ironic) sets boot mode first, boot device second system.set_system_boot_source( BOOT_DEVICE, enabled=sushy.BOOT_SOURCE_ENABLED_CONTINUOUS, mode=BOOT_MODE) # with Dell, patching System tree does not work as expected # we need to reboot for the new boot mode to take effect utils.reboot_system(system) LOG.info('set boot mode to %s', BOOT_MODE) manager_oem.set_virtual_boot_device( BOOT_DEVICE, persistent=False, manager=manager, system=system) LOG.info('set boot device to %s', BOOT_DEVICE) # real caller should better not use our way to reboot utils.reboot_system(system) LOG.info('system rebooted') return 0 if __name__ == '__main__': sys.exit(main()) ././@PaxHeader0000000000000000000000000000003200000000000011450 xustar000000000000000026 mtime=1662366240.82314 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/0000775000175000017500000000000000000000000022046 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/__init__.py0000664000175000017500000000000000000000000024145 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/base.py0000664000175000017500000000132400000000000023332 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # Copyright 2019 OpenStack Foundation # # 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. from oslotest import base class TestCase(base.BaseTestCase): """Test case base class for all unit tests""" ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8271399 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/0000775000175000017500000000000000000000000024543 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/export_configuration_idrac.json0000664000175000017500000001405000000000000033050 0ustar00zuulzuul00000000000000{ "SystemConfiguration": { "Comments": [ { "Comment": "Export type is Clone,RO,JSON,IncludeHash,Selective" }, { "Comment": "Exported configuration may contain commented attributes. Attributes may be commented due to dependency, destructive nature, preserving server identity or for security reasons." } ], "Model": "PowerEdge R640", "ServiceTag": "ABC1234", "TimeStamp": "Thu Nov 4 07:21:54 2021", "Components": [ { "FQDD": "iDRAC.Embedded.1", "Attributes": [ { "Name": "Info.1#Product", "Value": "Integrated Dell Remote Access Controller", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#Description", "Value": "This system component provides a complete set of remote management functions for Dell PowerEdge Servers", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#Version", "Value": "5.00.10.20", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#Build", "Value": "01", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#Name", "Value": "iDRAC", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#Type", "Value": "14G Monolithic", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "Info.1#ServerGen", "Value": "14G", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv4.1#Enable", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4.1#DHCPEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6.1#Enable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6.1#AutoConfig", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6.1#LinkLocalAddress", "Value": "2001:db8:3333:4444:5555:6666:7777:8888", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address2", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address3", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address4", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address5", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address6", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address7", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address8", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address9", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address10", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address11", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address12", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address13", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address14", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#Address15", "Value": "::", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#AddressState", "Value": "Active", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv6.1#DUID", "Value": "00:01:00:01:25:67:39:1b:f4:02:70:db:6c:88", "Set On Import": "False", "Comment": "Always Read Only" }, { "Name": "IPv4Static.1#Address", "Value": "192.168.88.13", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4Static.1#Netmask", "Value": "255.255.255.0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4Static.1#Gateway", "Value": "192.168.88.1", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4Static.1#DNS1", "Value": "0.0.0.0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4Static.1#DNS2", "Value": "0.0.0.0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv4Static.1#DNSFromDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#Address1", "Value": "::", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#Gateway", "Value": "::", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#PrefixLength", "Value": "64", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#DNS1", "Value": "::", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#DNS2", "Value": "::", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IPv6Static.1#DNSFromDHCP6", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" } ]} ]} } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/export_configuration_nic_bios.json0000664000175000017500000011707200000000000033563 0ustar00zuulzuul00000000000000{ "SystemConfiguration": { "Comments": [ { "Comment": "Export type is Normal,JSON,Selective" }, { "Comment": "Exported configuration may contain commented attributes. Attributes may be commented due to dependency, destructive nature, preserving server identity or for security reasons." } ], "Model": "PowerEdge R7525", "ServiceTag": "C6DCS33", "TimeStamp": "Wed Feb 3 06:53:31 2021", "Components": [ { "FQDD": "NIC.Integrated.1-4-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "8", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Integrated.1-2-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "8", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Integrated.1-3-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "PXE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "8", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Integrated.1-1-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "8", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Embedded.1-1-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "EEEControl", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "F4:02:70:B8:A6:7A", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IpAutoConfig", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiTgtBoot", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "DhcpVendId", "Value": "BRCM ISAN", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkUpDelayTime", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpTimestmp", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "FirstHddTarget", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LunBusyRetryCnt", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IpVer", "Value": "IPv4", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnetPrefix", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorPrimDns", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSecDns", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "iqn.1995-05.com.broadcom.iscsiboot", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ConnectFirstTgt", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ConnectSecondTgt", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondaryDeviceMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "UseIndTgtPortal", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "UseIndTgtName", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "BootOptionROM", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "BootStrapType", "Value": "AutoDetect", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "HideSetupPrompt", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "BannerMessageTimeout", "Value": "5", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanMode", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "1", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "PermitTotalPortShutdown", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Slot.1-2-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "NParEP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "64", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "INTEL_LLDPAgent", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapMutualAuth", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VFDistribution", "Value": "64:0:0:0:0:0:0:0", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Slot.1-1-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "NParEP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "64", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "INTEL_LLDPAgent", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapMutualAuth", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VFDistribution", "Value": "64:0:0:0:0:0:0:0", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Embedded.2-1-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "EEEControl", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "F4:02:70:B8:A6:7B", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IpAutoConfig", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiTgtBoot", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "DhcpVendId", "Value": "BRCM ISAN", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkUpDelayTime", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpTimestmp", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "FirstHddTarget", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LunBusyRetryCnt", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IpVer", "Value": "IPv4", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnetPrefix", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorPrimDns", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSecDns", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "iqn.1995-05.com.broadcom.iscsiboot", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ConnectFirstTgt", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ConnectSecondTgt", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "SecondaryDeviceMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "UseIndTgtPortal", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "UseIndTgtName", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "BootOptionROM", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "BootStrapType", "Value": "AutoDetect", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "HideSetupPrompt", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "BannerMessageTimeout", "Value": "5", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "LnkSpeed", "Value": "AutoNeg", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "WakeOnLan", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanMode", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "1", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "PermitTotalPortShutdown", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Slot.2-2-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "NParEP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "64", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "INTEL_LLDPAgent", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapMutualAuth", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VFDistribution", "Value": "64:0:0:0:0:0:0:0", "Set On Import": "False", "Comment": "Read and Write" } ] }, { "FQDD": "NIC.Slot.2-1-1", "Attributes": [ { "Name": "BlnkLeds", "Value": "0", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VirtMacAddr", "Value": "00:00:00:00:00:00", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VirtualizationMode", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "NParEP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "LegacyBootProto", "Value": "NONE", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "VLanId", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "NumberVFAdvertised", "Value": "64", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "INTEL_LLDPAgent", "Value": "Enabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "TcpIpViaDHCP", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "IscsiViaDHCP", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "ChapAuthEnable", "Value": "Disabled", "Set On Import": "True", "Comment": "Read and Write" }, { "Name": "ChapMutualAuth", "Value": "Disabled", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorIpAddr", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorSubnet", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorGateway", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapId", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "IscsiInitiatorChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIpAddress", "Value": "0.0.0.0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtTcpPort", "Value": "3260", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtBootLun", "Value": "0", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtIscsiName", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "FirstTgtChapPwd", "Value": "", "Set On Import": "False", "Comment": "Read and Write" }, { "Name": "VFDistribution", "Value": "64:0:0:0:0:0:0:0", "Set On Import": "False", "Comment": "Read and Write" } ] } ] } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/idrac_card_service.json0000664000175000017500000000131300000000000031227 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#DelliDRACCard.DelliDRACCardService", "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService", "@odata.type": "#DelliDRACCardService.v1_1_0.DelliDRACCardService", "Actions": { "#DelliDRACCardService.iDRACReset": { "Force@Redfish.AllowableValues": [ "Graceful", "Force" ], "target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService/Actions/DelliDRACCardService.iDRACReset" } }, "Description": "The DelliDRACCardService resource provides some actions to support iDRAC configurations.", "Id": "DelliDRACCardService", "Name": "DelliDRACCardService" } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/job_collection_expanded.json0000664000175000017500000000221600000000000032274 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#DellJobCollection.DellJobCollection", "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs", "@odata.type": "#DellJobCollection.DellJobCollection", "Description": "Collection of Job Instances", "Id": "JobQueue", "Members": [ { "@odata.context": "/redfish/v1/$metadata#DellJob.DellJob", "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs/RID_878460711202", "@odata.type": "#DellJob.v1_0_2.DellJob", "CompletionTime": "2020-04-25T15:21:33", "Description": "Job Instance", "EndTime": "TIME_NA", "Id": "RID_878460711202", "JobState": "Running", "JobType": "RebootForce", "Message": "Reboot is complete.", "MessageArgs": [ ], "MessageArgs@odata.count": 0, "MessageId": "RED030", "Name": "Reboot3", "PercentComplete": 100, "StartTime": "TIME_NOW", "TargetSettingsURI": null } ], "Name": "JobQueue" } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/job_service.json0000664000175000017500000000107100000000000027727 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#DellJobService.DellJobService", "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService", "@odata.type": "#DellJobService.v1_1_0.DellJobService", "Actions": { "#DellJobService.DeleteJobQueue": { "target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService/Actions/DellJobService.DeleteJobQueue" } }, "Description": "The DellJobService resource provides some actions to support Job management functionality.", "Id": "Job Service", "Name": "DellJobService" } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/lifecycle_service.json0000664000175000017500000000111700000000000031115 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#DellLCService.DellLCService", "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService", "@odata.type": "#DellLCService.v1_1_0.DellLCService", "Actions": { "#DellLCService.GetRemoteServicesAPIStatus": { "target": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService/Actions/DellLCService.GetRemoteServicesAPIStatus" } }, "Description": "The DellLCService resource provides some actions to support Lifecycle Controller functionality.", "Id": "DellLCService", "Name": "DellLCService" } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/manager.json0000664000175000017500000002405300000000000027054 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#Manager.Manager", "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1", "@odata.type": "#Manager.v1_3_3.Manager", "Actions": { "#Manager.Reset": { "ResetType@Redfish.AllowableValues": [ "GracefulRestart" ], "target": "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Manager.Reset" }, "Oem": { "DellManager.v1_0_0#DellManager.ResetToDefaults": { "ResetType@Redfish.AllowableValues": [ "All", "ResetAllWithRootDefaults", "Default" ], "target": "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/DellManager.ResetToDefaults" }, "OemManager.v1_0_0#OemManager.ExportSystemConfiguration": { "ExportFormat@Redfish.AllowableValues": [ "XML", "JSON" ], "ExportUse@Redfish.AllowableValues": [ "Default", "Clone", "Replace" ], "IncludeInExport@Redfish.AllowableValues": [ "Default", "IncludeReadOnly", "IncludePasswordHashValues" ], "ShareParameters": { "IgnoreCertificateWarning@Redfish.AllowableValues": [ "Disabled", "Enabled" ], "ProxySupport@Redfish.AllowableValues": [ "Disabled", "EnabledProxyDefault", "Enabled" ], "ProxyType@Redfish.AllowableValues": [ "HTTP", "SOCKS4" ], "ShareType@Redfish.AllowableValues": [ "LOCAL", "NFS", "CIFS", "HTTP", "HTTPS" ], "Target@Redfish.AllowableValues": [ "ALL", "IDRAC", "BIOS", "NIC", "RAID" ] }, "target": "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager.ExportSystemConfiguration" }, "OemManager.v1_0_0#OemManager.ImportSystemConfiguration": { "HostPowerState@Redfish.AllowableValues": [ "On", "Off" ], "ImportSystemConfiguration@Redfish.AllowableValues": [ "TimeToWait", "ImportBuffer" ], "ShareParameters": { "IgnoreCertificateWarning@Redfish.AllowableValues": [ "Disabled", "Enabled" ], "ProxySupport@Redfish.AllowableValues": [ "Disabled", "EnabledProxyDefault", "Enabled" ], "ProxyType@Redfish.AllowableValues": [ "HTTP", "SOCKS4" ], "ShareType@Redfish.AllowableValues": [ "LOCAL", "NFS", "CIFS", "HTTP", "HTTPS" ], "Target@Redfish.AllowableValues": [ "ALL", "IDRAC", "BIOS", "NIC", "RAID" ] }, "ShutdownType@Redfish.AllowableValues": [ "Graceful", "Forced", "NoReboot" ], "target": "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager.ImportSystemConfiguration" }, "OemManager.v1_0_0#OemManager.ImportSystemConfigurationPreview": { "ImportSystemConfigurationPreview@Redfish.AllowableValues": [ "ImportBuffer" ], "ShareParameters": { "IgnoreCertificateWarning@Redfish.AllowableValues": [ "Disabled", "Enabled" ], "ProxySupport@Redfish.AllowableValues": [ "Disabled", "EnabledProxyDefault", "Enabled" ], "ProxyType@Redfish.AllowableValues": [ "HTTP", "SOCKS4" ], "ShareType@Redfish.AllowableValues": [ "LOCAL", "NFS", "CIFS", "HTTP", "HTTPS" ], "Target@Redfish.AllowableValues": [ "ALL" ] }, "target": "/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager.ImportSystemConfigurationPreview" } } }, "CommandShell": { "ConnectTypesSupported": [ "SSH", "Telnet", "IPMI" ], "ConnectTypesSupported@odata.count": 3, "MaxConcurrentSessions": 5, "ServiceEnabled": true }, "DateTime": "2019-08-07T12:47:37-04:00", "DateTimeLocalOffset": "-04:00", "Description": "BMC", "EthernetInterfaces": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/EthernetInterfaces" }, "FirmwareVersion": "3.34.34.34", "GraphicalConsole": { "ConnectTypesSupported": [ "KVMIP" ], "ConnectTypesSupported@odata.count": 1, "MaxConcurrentSessions": 6, "ServiceEnabled": true }, "HostInterfaces": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/HostInterfaces" }, "Id": "iDRAC.Embedded.1", "Links": { "ManagerForChassis": [ { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1" } ], "ManagerForChassis@odata.count": 1, "ManagerForServers": [ { "@odata.id": "/redfish/v1/Systems/System.Embedded.1" } ], "ManagerForServers@odata.count": 1, "ManagerInChassis": { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1" }, "Oem": { "Dell": { "DellAttributes": [ { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Attributes" }, { "@odata.id": "/redfish/v1/Managers/System.Embedded.1/Attributes" }, { "@odata.id": "/redfish/v1/Managers/LifecycleController.Embedded.1/Attributes" } ], "DellAttributes@odata.count": 3, "DellJobService": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService" }, "DellLCService": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService" }, "DellLicenseCollection": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLicenseCollection" }, "DellLicenseManagementService": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLicenseManagementService" }, "DellPersistentStorageService": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellPersistentStorageService" }, "DellSwitchConnectionCollection": { "@odata.id": "/redfish/v1/Dell/Systems/System.Embedded.1/NetworkPorts/DellSwitchConnectionCollection" }, "DelliDRACCardService": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService" }, "DellvFlashCollection": { "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellvFlashCollection" }, "Jobs": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/Jobs" } } } }, "LogServices": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/LogServices" }, "ManagerType": "BMC", "Model": "14G Monolithic", "Name": "Manager", "NetworkProtocol": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/NetworkProtocol" }, "Oem": { "Dell": { "DelliDRACCard": { "@odata.context": "/redfish/v1/$metadata#DelliDRACCard.DelliDRACCard", "@odata.id": "/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCard/iDRAC.Embedded.1-1%23IDRACinfo", "@odata.type": "#DelliDRACCard.v1_0_0.DelliDRACCard", "IPMIVersion": "2.0", "URLString": "https://10.19.133.11:443" } } }, "PowerState": "On", "Redundancy": [], "Redundancy@odata.count": 0, "SerialConsole": { "ConnectTypesSupported": [], "ConnectTypesSupported@odata.count": 0, "MaxConcurrentSessions": 0, "ServiceEnabled": false }, "SerialInterfaces": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/SerialInterfaces" }, "Status": { "Health": "OK", "State": "Enabled" }, "UUID": "3256444f-c0c7-3780-5310-00544c4c4544", "VirtualMedia": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/VirtualMedia" } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/manager_collection.json0000664000175000017500000000056600000000000031272 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#ManagerCollection.ManagerCollection", "@odata.id": "/redfish/v1/Managers", "@odata.type": "#ManagerCollection.ManagerCollection", "Description": "BMC", "Members": [ { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1" } ], "Members@odata.count": 1, "Name": "Manager" } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/raid_service.json0000664000175000017500000002260600000000000030103 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#DellRaidService.DellRaidService", "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService", "@odata.type": "#DellRaidService.v1_3_0.DellRaidService", "Actions": { "#DellRaidService.AssignSpare": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.AssignSpare" }, "#DellRaidService.BlinkTarget": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.BlinkTarget" }, "#DellRaidService.CancelBackgroundInitialization": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.CancelBackgroundInitialization" }, "#DellRaidService.CancelCheckConsistency": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.CancelCheckConsistency" }, "#DellRaidService.CancelRebuildPhysicalDisk": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.CancelRebuildPhysicalDisk" }, "#DellRaidService.ChangePDState": { "State@Redfish.AllowableValues": [ "Offline", "Online" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ChangePDState" }, "#DellRaidService.CheckVDValues": { "VDPropNameArrayIn@Redfish.AllowableValues": [ "RAIDLevel", "Size", "SpanDepth", "SpanLength", "StartingLBA", "T10PIStatus" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.CheckVDValues" }, "#DellRaidService.ClearControllerPreservedCache": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ClearControllerPreservedCache" }, "#DellRaidService.ClearForeignConfig": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ClearForeignConfig" }, "#DellRaidService.ConvertToNonRAID": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ConvertToNonRAID" }, "#DellRaidService.ConvertToRAID": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ConvertToRAID" }, "#DellRaidService.EnableControllerEncryption": { "Mode@Redfish.AllowableValues": [ "DKM", "LKM", "SEKM" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.EnableControllerEncryption" }, "#DellRaidService.GetAvailableDisks": { "BlockSizeInBytes@Redfish.AllowableValues": [ "4096", "512", "All" ], "DiskEncrypt@Redfish.AllowableValues": [ "All", "FDE", "NonFDE" ], "DiskType@Redfish.AllowableValues": [ "All", "HDD", "SSD" ], "Diskprotocol@Redfish.AllowableValues": [ "AllProtocols", "NVMe", "SAS", "SATA" ], "FormFactor@Redfish.AllowableValues": [ "All", "M.2" ], "RaidLevel@Redfish.AllowableValues": [ "NoRAID", "RAID0", "RAID1", "RAID10", "RAID5", "RAID50", "RAID6", "RAID60" ], "T10PIStatus@Redfish.AllowableValues": [ "All", "T10PICapable", "T10PIIncapable" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.GetAvailableDisks" }, "#DellRaidService.GetDHSDisks": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.GetDHSDisks" }, "#DellRaidService.GetRAIDLevels": { "BlockSizeInBytes@Redfish.AllowableValues": [ "4096", "512", "All" ], "DiskEncrypt@Redfish.AllowableValues": [ "All", "FDE", "NonFDE" ], "DiskType@Redfish.AllowableValues": [ "All", "HDD", "SSD" ], "Diskprotocol@Redfish.AllowableValues": [ "AllProtocols", "NVMe", "SAS", "SATA" ], "FormFactor@Redfish.AllowableValues": [ "All", "M.2" ], "T10PIStatus@Redfish.AllowableValues": [ "All", "T10PICapable", "T10PIIncapable" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.GetRAIDLevels" }, "#DellRaidService.ImportForeignConfig": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ImportForeignConfig" }, "#DellRaidService.LockVirtualDisk": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.LockVirtualDisk" }, "#DellRaidService.OnlineCapacityExpansion": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.OnlineCapacityExpansion" }, "#DellRaidService.PrepareToRemove": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.PrepareToRemove" }, "#DellRaidService.RAIDLevelMigration": { "NewRaidLevel@Redfish.AllowableValues": [ "NoRAID", "RAID0", "RAID1", "RAID10", "RAID5", "RAID50", "RAID6", "RAID60" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.RAIDLevelMigration" }, "#DellRaidService.ReKey": { "Mode@Redfish.AllowableValues": [ "LKM", "SEKM" ], "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ReKey" }, "#DellRaidService.RebuildPhysicalDisk": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.RebuildPhysicalDisk" }, "#DellRaidService.RemoveControllerKey": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.RemoveControllerKey" }, "#DellRaidService.RenameVD": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.RenameVD" }, "#DellRaidService.ReplacePhysicalDisk": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ReplacePhysicalDisk" }, "#DellRaidService.ResetConfig": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.ResetConfig" }, "#DellRaidService.SetAssetName": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.SetAssetName" }, "#DellRaidService.SetBootVD": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.SetBootVD" }, "#DellRaidService.SetControllerKey": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.SetControllerKey" }, "#DellRaidService.StartPatrolRead": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.StartPatrolRead" }, "#DellRaidService.StopPatrolRead": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.StopPatrolRead" }, "#DellRaidService.UnBlinkTarget": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.UnBlinkTarget" }, "#DellRaidService.UnLockSecureForeignConfig": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.UnLockSecureForeignConfig" }, "#DellRaidService.UnassignSpare": { "target": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/Actions/DellRaidService.UnassignSpare" } }, "Description": "The DellRaidService resource provides some actions to support RAID functionality.", "Id": "DellRaidService", "Name": "DellRaidService" }././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/root.json0000664000175000017500000000352200000000000026423 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#ServiceRoot.ServiceRoot", "@odata.id": "/redfish/v1", "@odata.type": "#ServiceRoot.v1_3_0.ServiceRoot", "AccountService": { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1/AccountService" }, "Chassis": { "@odata.id": "/redfish/v1/Chassis" }, "Description": "Root Service", "EventService": { "@odata.id": "/redfish/v1/EventService" }, "Fabrics": { "@odata.id": "/redfish/v1/Fabrics" }, "Id": "RootService", "JsonSchemas": { "@odata.id": "/redfish/v1/JSONSchemas" }, "Links": { "Sessions": { "@odata.id": "/redfish/v1/Sessions" } }, "Managers": { "@odata.id": "/redfish/v1/Managers" }, "Name": "Root Service", "Oem": { "Dell": { "@odata.context": "/redfish/v1/$metadata#DellServiceRoot.DellServiceRoot", "@odata.type": "#DellServiceRoot.v1_0_0.ServiceRootSummary", "IsBranded": 0, "ManagerMACAddress": "4c:d9:8f:20:73:84", "ServiceTag": "GTS7DV2" } }, "Product": "Integrated Dell Remote Access Controller", "ProtocolFeaturesSupported": { "ExpandQuery": { "ExpandAll": true, "Levels": true, "Links": true, "MaxLevels": 1, "NoLinks": true }, "FilterQuery": true, "SelectQuery": true }, "RedfishVersion": "1.4.0", "Registries": { "@odata.id": "/redfish/v1/Registries" }, "SessionService": { "@odata.id": "/redfish/v1/SessionService" }, "Systems": { "@odata.id": "/redfish/v1/Systems" }, "Tasks": { "@odata.id": "/redfish/v1/TaskService" }, "UpdateService": { "@odata.id": "/redfish/v1/UpdateService" } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/storage_controller.json0000664000175000017500000000331000000000000031342 0ustar00zuulzuul00000000000000{ "@Redfish.Settings": { "@odata.context": "/redfish/v1/$metadata#Settings.Settings", "@odata.type": "#Settings.v1_3_3.Settings", "SettingsObject": { "@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1/Settings" }, "SupportedApplyTimes": [ "Immediate", "OnReset" ] }, "@odata.context": "/redfish/v1/$metadata#StorageController.StorageController", "@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1", "@odata.type": "#StorageController.v1_2_0.StorageController", "Description": "Integrated RAID Controller", "FirmwareVersion": "1.0.0.7", "Id": "1", "Identifiers": [ { "@odata.type": "#Resource.v1_1_0.Identifier", "DurableNameFormat": "NAA", "DurableName": "345C59DBD970859C" } ], "Identifiers@odata.count": 1, "Manufacturer": "Contoso", "Model": "12Gbs Integrated RAID", "Name": "Contoso Integrated RAID", "Oem": { "Dell": { "@odata.type": "#DellOemStorageController.v1_0_0.DellOemStorageController", "DellStorageController": { "ControllerMode": "EnhancedHBA" } } }, "SpeedGbps": 12, "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" }, "SupportedControllerProtocols": [ "PCIe" ], "SupportedControllerProtocols@odata.count": 1, "SupportedDeviceProtocols": [ "SAS", "SATA" ], "SupportedDeviceProtocols@odata.count": 2, "SupportedRAIDTypes": [ "RAID0", "RAID1" ], "SupportedRAIDTypes@odata.count": 2 } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/system.json0000664000175000017500000003515200000000000026770 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#ComputerSystem.ComputerSystem", "@odata.id": "/redfish/v1/Systems/System.Embedded.1", "@odata.type": "#ComputerSystem.v1_10_0.ComputerSystem", "Actions": { "#ComputerSystem.Reset": { "target": "/redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset", "ResetType@Redfish.AllowableValues": [ "On", "ForceOff", "ForceRestart", "GracefulRestart", "GracefulShutdown", "PushPowerButton", "Nmi", "PowerCycle" ] } }, "AssetTag": "", "Bios": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Bios" }, "BiosVersion": "2.10.2", "Boot": { "BootOptions": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/BootOptions" }, "Certificates": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Boot/Certificates" }, "BootOrder": [ "Boot0006", "Boot0009", "Boot0007", "Boot0005", "Boot0003", "Boot0004", "Boot0008", "Boot0002" ], "BootOrder@odata.count": 8, "BootSourceOverrideEnabled": "Disabled", "BootSourceOverrideMode": "UEFI", "BootSourceOverrideTarget": "None", "UefiTargetBootSourceOverride": null, "BootSourceOverrideTarget@Redfish.AllowableValues": [ "None", "Pxe", "Floppy", "Cd", "Hdd", "BiosSetup", "Utilities", "UefiTarget", "SDCard", "UefiHttp" ] }, "Description": "Computer System which represents a machine (physical or virtual) and the local resources such as memory, cpu and other devices that can be accessed from that machine.", "EthernetInterfaces": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/EthernetInterfaces" }, "HostName": "", "HostWatchdogTimer": { "FunctionEnabled": false, "Status": { "State": "Disabled" }, "TimeoutAction": "None" }, "HostingRoles": [], "HostingRoles@odata.count": 0, "Id": "System.Embedded.1", "IndicatorLED": "Lit", "Links": { "Chassis": [ { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1" } ], "Chassis@odata.count": 1, "CooledBy": [ { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/0" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/1" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/2" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/3" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/4" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/5" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/6" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/7" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/8" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/9" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/10" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/11" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/12" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/13" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/14" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Thermal#/Fans/15" } ], "CooledBy@odata.count": 16, "ManagedBy": [ { "@odata.id": "/redfish/v1/Managers/iDRAC.Embedded.1" } ], "ManagedBy@odata.count": 1, "Oem": { "Dell": { "@odata.type": "#DellOem.v1_1_0.DellOemLinks", "BootOrder": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources" }, "DellBootSources": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBootSources" }, "DellSoftwareInstallationService": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSoftwareInstallationService" }, "DellVideoCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellVideo" }, "DellChassisCollection": { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Oem/Dell/DellChassis" }, "DellPresenceAndStatusSensorCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellPresenceAndStatusSensors" }, "DellSensorCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSensors" }, "DellRollupStatusCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRollupStatus" }, "DellPSNumericSensorCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellPSNumericSensors" }, "DellVideoNetworkCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellVideoNetwork" }, "DellOSDeploymentService": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellOSDeploymentService" }, "DellMetricService": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellMetricService" }, "DellGPUSensorCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellGPUSensors" }, "DellRaidService": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService" }, "DellNumericSensorCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellNumericSensors" }, "DellBIOSService": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellBIOSService" }, "DellSlotCollection": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSlots" } } }, "PoweredBy": [ { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/0" }, { "@odata.id": "/redfish/v1/Chassis/System.Embedded.1/Power#/PowerSupplies/1" } ], "PoweredBy@odata.count": 2 }, "Manufacturer": "Dell Inc.", "Memory": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Memory" }, "MemorySummary": { "MemoryMirroring": "System", "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" }, "TotalSystemMemoryGiB": 192 }, "Model": "PowerEdge R640", "Name": "System", "NetworkInterfaces": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/NetworkInterfaces" }, "Oem": { "Dell": { "@odata.type": "#DellOem.v1_1_0.DellOemResources", "DellSystem": { "BIOSReleaseDate": "02/24/2021", "BaseBoardChassisSlot": "NA", "BatteryRollupStatus": "OK", "BladeGeometry": "NotApplicable", "CMCIP": null, "CPURollupStatus": "OK", "ChassisModel": "", "ChassisName": "Main System Chassis", "ChassisServiceTag": "8CYCZ23", "ChassisSystemHeightUnit": 1, "CurrentRollupStatus": "OK", "EstimatedExhaustTemperatureCelsius": 46, "EstimatedSystemAirflowCFM": 26, "ExpressServiceCode": "18197565051", "FanRollupStatus": "OK", "Id": "System.Embedded.1", "IDSDMRollupStatus": null, "IntrusionRollupStatus": "OK", "IsOEMBranded": "False", "LastSystemInventoryTime": "2021-06-16T09:46:25+00:00", "LastUpdateTime": "2021-05-31T15:39:10+00:00", "LicensingRollupStatus": "OK", "MaxCPUSockets": 2, "MaxDIMMSlots": 24, "MaxPCIeSlots": 3, "MemoryOperationMode": "OptimizerMode", "Name": "DellSystem", "NodeID": "8CYCZ23", "PSRollupStatus": "OK", "PlatformGUID": "33325a4f-c0b8-4380-5910-00434c4c4544", "PopulatedDIMMSlots": 12, "PopulatedPCIeSlots": 1, "PowerCapEnabledState": "Disabled", "SDCardRollupStatus": null, "SELRollupStatus": "OK", "ServerAllocationWatts": null, "StorageRollupStatus": "OK", "SysMemErrorMethodology": "Multi-bitECC", "SysMemFailOverState": "NotInUse", "SysMemLocation": "SystemBoardOrMotherboard", "SysMemPrimaryStatus": "OK", "SystemGeneration": "14G Monolithic", "SystemID": 1814, "SystemRevision": "I", "TempRollupStatus": "OK", "TempStatisticsRollupStatus": "OK", "UUID": "4c4c4544-0043-5910-8043-b8c04f5a3233", "VoltRollupStatus": "OK", "smbiosGUID": "44454c4c-4300-1059-8043-b8c04f5a3233", "@odata.context": "/redfish/v1/$metadata#DellSystem.DellSystem", "@odata.type": "#DellSystem.v1_2_0.DellSystem", "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellSystem/System.Embedded.1" } } }, "PCIeDevices": [ { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/25-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/24-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-28" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-23" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-31" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/3-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-17" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/59-0" } ], "PCIeDevices@odata.count": 9, "PCIeFunctions": [ { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/25-0/PCIeFunctions/25-0-1" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/24-0/PCIeFunctions/24-0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/25-0/PCIeFunctions/25-0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-28/PCIeFunctions/0-28-4" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-23/PCIeFunctions/0-23-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-31/PCIeFunctions/0-31-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-28/PCIeFunctions/0-28-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/3-0/PCIeFunctions/3-0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-0/PCIeFunctions/0-0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-17/PCIeFunctions/0-17-5" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/59-0/PCIeFunctions/59-0-1" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/59-0/PCIeFunctions/59-0-0" }, { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/PCIeDevices/0-31/PCIeFunctions/0-31-4" } ], "PCIeFunctions@odata.count": 13, "PartNumber": "06NR82A02", "PowerState": "On", "ProcessorSummary": { "Count": 2, "LogicalProcessorCount": 80, "Model": "Intel(R) Xeon(R) Gold 6230 CPU @ 2.10GHz", "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" } }, "Processors": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Processors" }, "SKU": "8CYCZ23", "SecureBoot": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/SecureBoot" }, "SerialNumber": "CNIVC000180873", "SimpleStorage": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/SimpleStorage" }, "Status": { "Health": "OK", "HealthRollup": "OK", "State": "Enabled" }, "Storage": { "@odata.id": "/redfish/v1/Systems/System.Embedded.1/Storage" }, "SystemType": "Physical", "TrustedModules": [ { "FirmwareVersion": "Unknown", "InterfaceType": null, "Status": { "State": "Disabled" } } ], "TrustedModules@odata.count": 1, "UUID": "4c4c4544-0043-5910-8043-b8c04f5a3233" }././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/json_samples/task.json0000664000175000017500000000243200000000000026401 0ustar00zuulzuul00000000000000{ "@odata.context": "/redfish/v1/$metadata#Task.Task", "@odata.id": "/redfish/v1/TaskService/Tasks/JID_257309938313", "@odata.type": "#Task.v1_4_3.Task", "Description": "Server Configuration and other Tasks running on iDRAC are listed here", "Id": "JID_257309938313", "Messages": [ { "Message": "Task successfully scheduled.", "MessageArgs": [], "MessageArgs@odata.count": 0, "MessageId": "IDRAC.2.5.JCP001" } ], "Messages@odata.count": 1, "Name": "Configure: RAID.Integrated.1-1", "Oem": { "Dell": { "@odata.type": "#DellJob.v1_1_0.DellJob", "CompletionTime": null, "Description": "Job Instance", "EndTime": "TIME_NA", "Id": "JID_257309938313", "JobState": "Scheduled", "JobType": "RAIDConfiguration", "Message": "Task successfully scheduled.", "MessageArgs": [], "MessageId": "IDRAC.2.5.JCP001", "Name": "Configure: RAID.Integrated.1-1", "PercentComplete": 0, "StartTime": "TIME_NOW", "TargetSettingsURI": null } }, "PercentComplete": 0, "TaskState": "Starting", "TaskStatus": "OK" }././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8271399 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/0000775000175000017500000000000000000000000024060 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/__init__.py0000664000175000017500000000000000000000000026157 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8271399 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/0000775000175000017500000000000000000000000025472 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/__init__.py0000664000175000017500000000000000000000000027571 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/test_idrac_card_service.py0000664000175000017500000000542100000000000032700 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy_oem_idrac.resources.manager import constants as mgr_cons from sushy_oem_idrac.resources.manager import idrac_card_service class DelliDRACCardServiceTestCase(BaseTestCase): def setUp(self): super(DelliDRACCardServiceTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'idrac_card_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers.get.return_value = '1' self.idrac_card_service = idrac_card_service.DelliDRACCardService( self.conn, '/redfish/v1/Dell/Managers/iDRAC.Embedded.1') def test_reset_idrac(self): self.idrac_card_service.reset_idrac() target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1' '/DelliDRACCardService' '/Actions/DelliDRACCardService.iDRACReset') self.conn.post.assert_called_once_with(target_uri, data={'Force': 'Graceful'}) def test_get_allowed_reset_idrac_values(self): expected_values = {mgr_cons.ResetType.GRACEFUL, mgr_cons.ResetType.FORCE} allowed_values = \ self.idrac_card_service.get_allowed_reset_idrac_values() self.assertEqual(expected_values, allowed_values) def test_get_allowed_reset_idrac_values_not_provided_by_idrac(self): idrac_service_json = self.idrac_card_service.json base_property = '#DelliDRACCardService.iDRACReset' remove_property = 'Force@Redfish.AllowableValues' idrac_service_json['Actions'][base_property].pop(remove_property) expected_values = {mgr_cons.ResetType.GRACEFUL, mgr_cons.ResetType.FORCE} allowed_values = \ self.idrac_card_service.get_allowed_reset_idrac_values() self.assertEqual(expected_values, allowed_values) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/test_job_collection.py0000664000175000017500000000351600000000000032075 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy_oem_idrac.resources.manager import job_collection class DellJobCollectionTestCase(BaseTestCase): def setUp(self): super(DellJobCollectionTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'job_collection_expanded.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers.get.return_value = '1' self.job_collection = job_collection.DellJobCollection( self.conn, '/redfish/v1/Managers/iDRAC.Embedded.1/Jobs') def test_get_unfinished_jobs(self): expected_unfinished_jobs = ['RID_878460711202'] actual_unfinished_jobs = self.job_collection.get_unfinished_jobs() target_uri = ('/redfish/v1/Managers/iDRAC.Embedded.1' '/Jobs?$expand=.($levels=1)') self.conn.get.assert_called_with(target_uri) self.assertEqual(expected_unfinished_jobs, actual_unfinished_jobs) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/test_job_service.py0000664000175000017500000000367400000000000031407 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy_oem_idrac.resources.manager import job_service class DellJobServiceTestCase(BaseTestCase): def setUp(self): super(DellJobServiceTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'job_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers.get.return_value = '1' self.job_service = job_service.DellJobService( self.conn, '/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService') def test_delete_jobs(self): job_ids = ['JID_471269252011', 'JID_471269252012'] self.job_service.delete_jobs(job_ids=job_ids) target_uri = ('/redfish/v1/Dell/Managers' '/iDRAC.Embedded.1/DellJobService' '/Actions/''DellJobService.DeleteJobQueue') for job_id in job_ids: self.conn.post.assert_any_call(target_uri, data={'JobID': job_id}) self.assertEqual(2, self.conn.post.call_count) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/test_lifecycle_service.py0000664000175000017500000001012200000000000032556 0ustar00zuulzuul00000000000000# Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy_oem_idrac.resources.manager import lifecycle_service class DellLCServiceTestCase(BaseTestCase): def setUp(self): super(DellLCServiceTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'lifecycle_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers.get.return_value = '1' self.lifecycle_service = lifecycle_service.DellLCService( self.conn, '/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService') def test_is_idrac_ready_true(self): mock_response = self.conn.post.return_value mock_response.status_code = 200 mock_response.json.return_value = { "LCStatus": "Ready", "RTStatus": "Ready", "ServerStatus": "OutOfPOST", "Status": "Ready" } target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1' '/DellLCService' '/Actions/DellLCService.GetRemoteServicesAPIStatus') idrac_ready_response = self.lifecycle_service.is_idrac_ready() self.conn.post.assert_called_once_with(target_uri, data={}) self.assertTrue(idrac_ready_response) def test_is_idrac_ready_false(self): mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.json.return_value = { "LCStatus": "NotReady", "RTStatus": "NotReady", "ServerStatus": "OutOfPOST", "Status": "NotReady" } target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1' '/DellLCService' '/Actions/DellLCService.GetRemoteServicesAPIStatus') idrac_ready_response = self.lifecycle_service.is_idrac_ready() self.conn.post.assert_called_once_with(target_uri, data={}) self.assertFalse(idrac_ready_response) def test_is_realtime_ready_true(self): mock_response = self.conn.post.return_value mock_response.status_code = 200 mock_response.json.return_value = { "LCStatus": "Ready", "RTStatus": "Ready", "ServerStatus": "OutOfPOST", "Status": "Ready" } self.assertTrue(self.lifecycle_service.is_realtime_ready()) target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1' '/DellLCService' '/Actions/DellLCService.GetRemoteServicesAPIStatus') self.conn.post.assert_called_once_with(target_uri, data={}) def test_is_realtime_ready_false(self): mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.json.return_value = { "LCStatus": "Ready", "RTStatus": "NotReady", "ServerStatus": "OutOfPOST", "Status": "NotReady" } self.assertFalse(self.lifecycle_service.is_realtime_ready()) target_uri = ('/redfish/v1/Dell/Managers/iDRAC.Embedded.1' '/DellLCService' '/Actions/DellLCService.GetRemoteServicesAPIStatus') self.conn.post.assert_called_once_with(target_uri, data={}) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/manager/test_manager.py0000664000175000017500000007136700000000000030533 0ustar00zuulzuul00000000000000# Copyright 2017 Red Hat, Inc. # All Rights Reserved. # Copyright (c) 2020-2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase import sushy from sushy.resources.manager import manager from sushy.taskmonitor import TaskMonitor from sushy_oem_idrac.resources.manager import constants as mgr_cons from sushy_oem_idrac.resources.manager import idrac_card_service as idrac_card from sushy_oem_idrac.resources.manager import job_collection as jc from sushy_oem_idrac.resources.manager import job_service as job from sushy_oem_idrac.resources.manager import lifecycle_service as lifecycle from sushy_oem_idrac.resources.manager import manager as oem_manager class ManagerTestCase(BaseTestCase): def setUp(self): super(ManagerTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'manager.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers = { 'Location': '/redfish/v1/TaskService/Tasks/JID_905749031119'} mock_response.content = None self.manager = manager.Manager(self.conn, '/redfish/v1/Managers/BMC', redfish_version='1.0.2') @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_import_system_configuration_uri(self): oem = self.manager.get_oem_extension('Dell') self.assertEqual( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ImportSystemConfiguration', oem.import_system_configuration_uri) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_set_virtual_boot_device_cd(self): oem = self.manager.get_oem_extension('Dell') oem.set_virtual_boot_device( sushy.VIRTUAL_MEDIA_CD, manager=self.manager) self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ImportSystemConfiguration', data={'ShareParameters': {'Target': 'ALL'}, 'ImportBuffer': '' 'Enabled' 'VCD-DVD' ''}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_set_virtual_boot_device_cd_no_manager_passed(self): oem = self.manager.get_oem_extension('Dell') oem.set_virtual_boot_device(sushy.VIRTUAL_MEDIA_CD) self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ImportSystemConfiguration', data={'ShareParameters': {'Target': 'ALL'}, 'ImportBuffer': '' 'Enabled' 'VCD-DVD' ''}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_allowed_export_target_values(self): oem = self.manager.get_oem_extension('Dell') expected_values = {mgr_cons.ExportTarget.IDRAC, mgr_cons.ExportTarget.RAID, mgr_cons.ExportTarget.ALL, mgr_cons.ExportTarget.BIOS, mgr_cons.ExportTarget.NIC} allowed_values = oem.get_allowed_export_target_values() self.assertEqual(expected_values, allowed_values) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_allowed_export_target_values_missing(self): oem = self.manager.get_oem_extension('Dell') export_action = ('OemManager.v1_0_0' '#OemManager.ExportSystemConfiguration') oem.json['Actions']['Oem'][export_action]['ShareParameters'].pop( 'Target@Redfish.AllowableValues') oem.refresh() oem = self.manager.get_oem_extension('Dell') expected_values = {mgr_cons.ExportTarget.IDRAC, mgr_cons.ExportTarget.RAID, mgr_cons.ExportTarget.ALL, mgr_cons.ExportTarget.BIOS, mgr_cons.ExportTarget.NIC} allowed_values = oem.get_allowed_export_target_values() self.assertEqual(expected_values, allowed_values) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_export_system_configuration_uri(self): oem = self.manager.get_oem_extension('Dell') self.assertEqual( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ExportSystemConfiguration', oem.export_system_configuration_uri) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test__export_system_configuration(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration( target=mgr_cons.ExportTarget.ALL) self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ExportSystemConfiguration', data={'ShareParameters': {'Target': 'ALL'}, 'ExportFormat': 'JSON', 'ExportUse': 'Default', 'IncludeInExport': 'Default'}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test__export_system_configuration_nondefault(self): oem = self.manager.get_oem_extension('Dell') include_in_export = mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES oem._export_system_configuration( target=mgr_cons.ExportTarget.RAID, export_use=mgr_cons.ExportUse.CLONE, include_in_export=include_in_export) self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ExportSystemConfiguration', data={'ShareParameters': {'Target': 'RAID'}, 'ExportFormat': 'JSON', 'ExportUse': 'Clone', 'IncludeInExport': 'IncludeReadOnly,Include' 'PasswordHashValues'}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test__export_system_configuration_invalid_target(self): oem = self.manager.get_oem_extension('Dell') target = "xyz" self.assertRaises(sushy.exceptions.InvalidParameterValueError, oem._export_system_configuration, target) def test__export_system_configuration_invalid_export_use(self): oem = self.manager.get_oem_extension('Dell') self.assertRaises(sushy.exceptions.InvalidParameterValueError, oem._export_system_configuration, mgr_cons.ExportTarget.RAID, export_use="ABC") def test__export_system_configuration_invalid_include_in_export(self): oem = self.manager.get_oem_extension('Dell') self.assertRaises(sushy.exceptions.InvalidParameterValueError, oem._export_system_configuration, mgr_cons.ExportTarget.RAID, include_in_export="ABC") def test__export_system_configuration_invalid_include_in_export_part(self): oem = self.manager.get_oem_extension('Dell') export_action = ('OemManager.v1_0_0' '#OemManager.ExportSystemConfiguration') # Remove `IncludePasswordHashValues` from allowed values oem.json['Actions']['Oem'][export_action]['IncludeInExport@Redfish.' 'AllowableValues'] =\ ['Default', 'IncludeReadOnly'] oem.refresh() oem = self.manager.get_oem_extension('Dell') include_in_export = mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES self.assertRaises(sushy.exceptions.InvalidParameterValueError, oem._export_system_configuration, mgr_cons.ExportTarget.RAID, include_in_export=include_in_export) def test__export_system_configuration_include_in_export_legacy( self): oem = self.manager.get_oem_extension('Dell') export_action = ('OemManager.v1_0_0' '#OemManager.ExportSystemConfiguration') # Add `IncludeReadOnly,IncludePasswordHashValues` to allowed values oem.json['Actions']['Oem'][export_action]['IncludeInExport@Redfish.' 'AllowableValues'] =\ ['Default', 'IncludeReadOnly', 'IncludePasswordHashValues', 'IncludeReadOnly,IncludePasswordHashValues'] oem.refresh() include_in_export = mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES oem._export_system_configuration( target=mgr_cons.ExportTarget.RAID, export_use=mgr_cons.ExportUse.CLONE, include_in_export=include_in_export) self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ExportSystemConfiguration', data={'ShareParameters': {'Target': 'RAID'}, 'ExportFormat': 'JSON', 'ExportUse': 'Clone', 'IncludeInExport': 'IncludeReadOnly,Include' 'PasswordHashValues'}) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_allowed_export_use_values(self): oem = self.manager.get_oem_extension('Dell') expected_values = {mgr_cons.ExportUse.DEFAULT, mgr_cons.ExportUse.CLONE, mgr_cons.ExportUse.REPLACE} allowed_values = oem.get_allowed_export_use_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) @mock.patch.object(oem_manager, 'LOG', autospec=True) def test_get_allowed_export_use_values_missing(self, mock_log): oem = self.manager.get_oem_extension('Dell') export_action = ('OemManager.v1_0_0' '#OemManager.ExportSystemConfiguration') oem.json['Actions']['Oem'][export_action].pop( 'ExportUse@Redfish.AllowableValues') oem.refresh() expected_values = {mgr_cons.ExportUse.DEFAULT, mgr_cons.ExportUse.CLONE, mgr_cons.ExportUse.REPLACE} allowed_values = oem.get_allowed_export_use_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) mock_log.warning.assert_called_once() @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_allowed_include_in_export_values(self): oem = self.manager.get_oem_extension('Dell') expected_values = {mgr_cons.IncludeInExport.DEFAULT, mgr_cons.IncludeInExport.READ_ONLY, mgr_cons.IncludeInExport.PASSWORD_HASHES} allowed_values = oem.get_allowed_include_in_export_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) @mock.patch.object(oem_manager, 'LOG', autospec=True) def test_get_allowed_include_in_export_values_missing(self, mock_log): oem = self.manager.get_oem_extension('Dell') export_action = ('OemManager.v1_0_0' '#OemManager.ExportSystemConfiguration') oem.json['Actions']['Oem'][export_action].pop( 'IncludeInExport@Redfish.AllowableValues') oem.refresh() expected_values = {mgr_cons.IncludeInExport.DEFAULT, mgr_cons.IncludeInExport.READ_ONLY, mgr_cons.IncludeInExport.PASSWORD_HASHES, mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES} allowed_values = oem.get_allowed_include_in_export_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) mock_log.warning.assert_called_once() @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_export_system_configuration(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration = mock.Mock() mock_response = mock.Mock() oem._export_system_configuration.return_value = mock_response response = oem.export_system_configuration() self.assertEqual(mock_response, response) include_in_export = mgr_cons.IncludeInExport.READ_ONLY_PASSWORD_HASHES oem._export_system_configuration.assert_called_once_with( mgr_cons.ExportTarget.ALL, export_use=mgr_cons.ExportUse.CLONE, include_in_export=include_in_export) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_export_system_configuration_destructive_fields(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'export_configuration_idrac.json') as f: mock_response = oem._export_system_configuration.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 response = oem.export_system_configuration( include_destructive_fields=False) response_json = json.loads(response._content) # From 40 items in test data 16 should be removed self.assertEqual(24, len(response_json['SystemConfiguration'] ['Components'][0]['Attributes'])) include_in_export = mgr_cons.INCLUDE_EXPORT_READ_ONLY_PASSWORD_HASHES oem._export_system_configuration.assert_called_once_with( mgr_cons.EXPORT_TARGET_ALL, export_use=mgr_cons.EXPORT_USE_CLONE, include_in_export=include_in_export) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_pxe_port_macs_bios(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'export_configuration_nic_bios.json') as f: mock_response = oem._export_system_configuration.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 ethernet_interfaces_mac = {'NIC.Integrated.1-4-1': '68:05:CA:AF:AA:C9', 'NIC.Slot.7-2-1': '3C:FD:FE:CD:67:31', 'NIC.Slot.7-1-1': '3C:FD:FE:CD:67:30', 'NIC.Integrated.1-2-1': '68:05:CA:AF:AA:C7', 'NIC.Integrated.1-3-1': '68:05:CA:AF:AA:C8', 'NIC.Integrated.1-1-1': '68:05:CA:AF:AA:C6'} self.assertEqual(["68:05:CA:AF:AA:C8"], oem.get_pxe_port_macs_bios(ethernet_interfaces_mac)) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_pxe_port_macs_bios_invalid_system_config_tag(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration = mock.Mock() mock_response = oem._export_system_configuration.return_value mock_response.json.return_value = {'Model': 'PowerEdge R7525'} mock_response.status_code = 200 ethernet_interfaces_mac = {'NIC.Integrated.1-4-1': '68:05:CA:AF:AA:C9', 'NIC.Slot.7-2-1': '3C:FD:FE:CD:67:31', 'NIC.Slot.7-1-1': '3C:FD:FE:CD:67:30', 'NIC.Integrated.1-2-1': '68:05:CA:AF:AA:C7', 'NIC.Integrated.1-3-1': '68:05:CA:AF:AA:C8', 'NIC.Integrated.1-1-1': '68:05:CA:AF:AA:C6'} self.assertRaises(sushy.exceptions.ExtensionError, oem.get_pxe_port_macs_bios, ethernet_interfaces_mac) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_get_pxe_port_macs_bios_invalid_response(self): oem = self.manager.get_oem_extension('Dell') oem._export_system_configuration = mock.Mock() mock_response = oem._export_system_configuration.return_value mock_response.status_code = 204 ethernet_interfaces_mac = {'NIC.Integrated.1-4-1': '68:05:CA:AF:AA:C9', 'NIC.Slot.7-2-1': '3C:FD:FE:CD:67:31', 'NIC.Slot.7-1-1': '3C:FD:FE:CD:67:30', 'NIC.Integrated.1-2-1': '68:05:CA:AF:AA:C7', 'NIC.Integrated.1-3-1': '68:05:CA:AF:AA:C8', 'NIC.Integrated.1-1-1': '68:05:CA:AF:AA:C6'} self.assertRaises(sushy.exceptions.ExtensionError, oem.get_pxe_port_macs_bios, ethernet_interfaces_mac) def test_idrac_card_service(self): oem = self.manager.get_oem_extension('Dell') with open('sushy_oem_idrac/tests/unit/json_samples/' 'idrac_card_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 idrac_card_service = oem.idrac_card_service self.assertEqual( '/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DelliDRACCardService', idrac_card_service.path) self.assertIsInstance(idrac_card_service, idrac_card.DelliDRACCardService) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_lifecycle_service(self): oem = self.manager.get_oem_extension('Dell') with open('sushy_oem_idrac/tests/unit/json_samples/' 'lifecycle_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 lifecycle_service = oem.lifecycle_service self.assertEqual( '/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellLCService', lifecycle_service.path) self.assertIsInstance(lifecycle_service, lifecycle.DellLCService) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_job_service(self): oem = self.manager.get_oem_extension('Dell') with open('sushy_oem_idrac/tests/unit/json_samples/' 'job_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 job_service = oem.job_service self.assertEqual( '/redfish/v1/Dell/Managers/iDRAC.Embedded.1/DellJobService', job_service.path) self.assertIsInstance(job_service, job.DellJobService) @mock.patch('sushy.resources.oem.common._global_extn_mgrs_by_resource', {}) def test_job_collection(self): oem = self.manager.get_oem_extension('Dell') with open('sushy_oem_idrac/tests/unit/json_samples/' 'job_collection_expanded.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 job_collection = oem.job_collection self.assertEqual( '/redfish/v1/Managers/iDRAC.Embedded.1/Jobs', job_collection.path) self.assertIsInstance(job_collection, jc.DellJobCollection) def test_get_allowed_import_shutdown_type_values(self): oem = self.manager.get_oem_extension('Dell') expected_values = {mgr_cons.ShutdownType.GRACEFUL, mgr_cons.ShutdownType.FORCED, mgr_cons.ShutdownType.NO_REBOOT} allowed_values = oem.get_allowed_import_shutdown_type_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) @mock.patch.object(oem_manager, 'LOG', autospec=True) def test_get_allowed_import_shutdown_type_values_missing(self, mock_log): oem = self.manager.get_oem_extension('Dell') import_action = ('OemManager.v1_0_0' '#OemManager.ImportSystemConfiguration') oem.json['Actions']['Oem'][import_action].pop( 'ShutdownType@Redfish.AllowableValues') oem.refresh() expected_values = {mgr_cons.ShutdownType.GRACEFUL, mgr_cons.ShutdownType.FORCED, mgr_cons.ShutdownType.NO_REBOOT} allowed_values = oem.get_allowed_import_shutdown_type_values() self.assertIsInstance(allowed_values, set) self.assertEqual(expected_values, allowed_values) mock_log.warning.assert_called_once() def test_import_system_configuration(self): oem = self.manager.get_oem_extension('Dell') result = oem.import_system_configuration('{"key": "value"}') self.conn.post.assert_called_once_with( '/redfish/v1/Managers/iDRAC.Embedded.1/Actions/Oem/EID_674_Manager' '.ImportSystemConfiguration', data={'ShareParameters': {'Target': 'ALL'}, 'ImportBuffer': '{"key": "value"}', 'ShutdownType': 'NoReboot'}) self.assertIsInstance(result, TaskMonitor) self.assertEqual('/redfish/v1/TaskService/Tasks/JID_905749031119', result.task_monitor_uri) def test_reset_idrac_with_wait_true(self): oem_manager = self.manager.get_oem_extension('Dell') oem_manager.idrac_card_service.reset_idrac = mock.Mock() oem_manager._conn._url = "https://1.2.3.4" oem_manager._wait_for_idrac = mock.Mock() oem_manager._wait_until_idrac_is_ready = mock.Mock() oem_manager.reset_idrac(wait=True) oem_manager.idrac_card_service.reset_idrac.assert_called() oem_manager._wait_for_idrac.assert_called_with('1.2.3.4', 60) oem_manager._wait_until_idrac_is_ready.assert_called_with( '1.2.3.4', 96, 10) def test_reset_idrac_with_wait_false(self): oem_manager = self.manager.get_oem_extension('Dell') oem_manager.idrac_card_service.reset_idrac = mock.Mock() oem_manager._wait_for_idrac = mock.Mock() oem_manager._wait_until_idrac_is_ready = mock.Mock() oem_manager.reset_idrac(wait=False) oem_manager.idrac_card_service.reset_idrac.assert_called() oem_manager._wait_for_idrac.assert_not_called() oem_manager._wait_until_idrac_is_ready.assert_not_called() def test__wait_until_idrac_is_ready(self): oem_manager = self.manager.get_oem_extension('Dell') oem_manager.lifecycle_service.is_idrac_ready = mock.Mock() oem_manager.lifecycle_service.is_idrac_ready.side_effect = \ [False, True] oem_manager._wait_until_idrac_is_ready('1.2.3.4', 96, 10) oem_manager.lifecycle_service.is_idrac_ready.assert_called_with() @mock.patch('time.sleep', autospec=True) def test__wait_until_idrac_is_ready_with_timeout(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager.lifecycle_service.is_idrac_ready = mock.Mock() oem_manager.lifecycle_service.is_idrac_ready.return_value = False self.assertRaises(sushy.exceptions.ExtensionError, oem_manager._wait_until_idrac_is_ready, '1.2.3.4', 96, 10) @mock.patch('time.sleep', autospec=True) def test__wait_for_idrac_with_state_reached(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager._wait_for_idrac_state = mock.Mock() oem_manager._wait_for_idrac_state.return_value = True oem_manager._wait_for_idrac('1.2.3.4', 30) oem_manager._wait_for_idrac_state.assert_called_with( '1.2.3.4', alive=True, ping_count=3, retries=24) oem_manager._wait_for_idrac_state.assert_any_call( '1.2.3.4', alive=False, ping_count=2, retries=24) self.assertEqual(2, oem_manager._wait_for_idrac_state.call_count) @mock.patch('time.sleep', autospec=True) def test__wait_for_idrac_with_first_state_not_reached(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager._wait_for_idrac_state = mock.Mock() oem_manager._wait_for_idrac_state.return_value = False self.assertRaises(sushy.exceptions.ExtensionError, oem_manager._wait_for_idrac, '1.2.3.4', 30) @mock.patch('time.sleep', autospec=True) def test__wait_for_idrac_with_second_state_not_reached(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager._wait_for_idrac_state = mock.Mock() oem_manager._wait_for_idrac_state.side_effect = [True, False] self.assertRaises(sushy.exceptions.ExtensionError, oem_manager._wait_for_idrac, '1.2.3.4', 30) @mock.patch('time.sleep', autospec=True) def test__wait_for_idrac_state_with_pingable(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager._ping_host = mock.Mock() oem_manager._ping_host.return_value = True response = oem_manager._wait_for_idrac_state('1.2.3.4') self.assertEqual(True, response) self.assertEqual(3, oem_manager._ping_host.call_count) @mock.patch('time.sleep', autospec=True) def test__wait_for_idrac_state_without_pingable(self, mock_time_sleep): oem_manager = self.manager.get_oem_extension('Dell') oem_manager._ping_host = mock.Mock() oem_manager._ping_host.return_value = False response = oem_manager._wait_for_idrac_state('1.2.3.4') self.assertEqual(False, response) self.assertEqual(24, oem_manager._ping_host.call_count) @mock.patch('subprocess.call', autospec=True) def test__ping_host_alive(self, mock_call): oem_manager = self.manager.get_oem_extension('Dell') mock_call.return_value = 0 result = oem_manager._ping_host('1.2.3.4') self.assertTrue(result) mock_call.assert_called_with(["ping", "-c", "1", '1.2.3.4']) @mock.patch('subprocess.call', autospec=True) def test__ping_host_not_alive(self, mock_call): oem_manager = self.manager.get_oem_extension('Dell') mock_call.return_value = 1 result = oem_manager._ping_host('1.2.3.4') self.assertFalse(result) mock_call.assert_called_with(["ping", "-c", "1", '1.2.3.4']) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/0000775000175000017500000000000000000000000025404 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/__init__.py0000664000175000017500000000000000000000000027503 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/storage/0000775000175000017500000000000000000000000027050 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/storage/__init__.py0000664000175000017500000000000000000000000031147 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/storage/test_controller.py0000664000175000017500000000570500000000000032653 0ustar00zuulzuul00000000000000# Copyright (c) 2022 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase import sushy from sushy.resources.system.storage import controller as sushy_constroller from sushy_oem_idrac.resources.system.storage import constants as ctrl_cons from sushy_oem_idrac.resources.system.storage import controller as oem_ctrl class ControllerTestCase(BaseTestCase): def setUp(self): super(ControllerTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'storage_controller.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 self.controller = sushy_constroller.StorageController( self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1') self.oem_controller = oem_ctrl.DellStorageControllerExtension( self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1') self.oem_controller = self.oem_controller.set_parent_resource( self.controller, 'Dell') def test_parse_attributes(self): self.assertEqual( ctrl_cons.ControllerMode.EHBA, self.oem_controller.dell_storage_controller.controller_mode) def test_convert_to_raid(self): mock_controller = mock.Mock() mock_task_monitor = mock.Mock() mock_controller.update.return_value = mock_task_monitor self.oem_controller._parent_resource = mock_controller res = self.oem_controller.convert_to_raid() self.assertEqual(mock_task_monitor, res) patch = {"Oem": {"Dell": {"DellStorageController": { "ControllerMode": "RAID"}}}} mock_controller.update.assert_called_once_with( patch, apply_time=sushy.ApplyTime.ON_RESET) def test_convert_to_raid_already_raid(self): mock_controller = mock.Mock() self.oem_controller._parent_resource = mock_controller json = self.oem_controller.json json['Oem']['Dell']['DellStorageController']['ControllerMode'] = 'RAID' self.oem_controller.refresh() res = self.oem_controller.convert_to_raid() self.assertIsNone(res) mock_controller.update.assert_not_called() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/test_raid_service.py0000664000175000017500000002150000000000000031452 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy import exceptions from sushy import taskmonitor from sushy_oem_idrac.resources.system import raid_service class DellRaidService(BaseTestCase): def setUp(self): super(DellRaidService, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'raid_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 self.mock_response = mock.Mock() self.mock_response.status_code = 202 self.mock_response.headers = { 'Location': '/redfish/v1/Managers/iDRAC.Embedded.1/Oem/Dell/Jobs/' 'JID_999888777666' } self.root = mock.Mock() self.raid_service = raid_service.DellRaidService( self.conn, '/redfish/v1/Systems/System.Embedded.1/Oem/Dell/' 'DellRaidService', root=self.root ) @mock.patch.object(raid_service.DellRaidService, '_get_task_monitor_from_dell_job', autospec=True) def test_convert_to_raid(self, mock_get_task_mon): mock_task_mon = mock.Mock() mock_get_task_mon.return_value = mock_task_mon fqdds = ["Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1", "Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1"] task_mon = self.raid_service.convert_to_raid(fqdds) self.conn.post.assert_called_once_with( '/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/' 'Actions/DellRaidService.ConvertToRAID', data={'PDArray': fqdds}) self.assertEqual(mock_task_mon, task_mon) @mock.patch.object(raid_service.DellRaidService, '_get_task_monitor_from_dell_job', autospec=True) def test_convert_to_nonraid(self, mock_get_task_mon): mock_task_mon = mock.Mock() mock_get_task_mon.return_value = mock_task_mon fqdds = ["Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1", "Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1"] task_mon = self.raid_service.convert_to_nonraid(fqdds) self.conn.post.assert_called_once_with( '/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/' 'Actions/DellRaidService.ConvertToNonRAID', data={'PDArray': fqdds}) self.assertEqual(mock_task_mon, task_mon) @mock.patch.object(raid_service.DellRaidService, '_get_task_monitor_from_dell_job', autospec=True) def test_clear_foreign_config(self, mock_get_task_mon): mock_task_mon = mock.Mock() mock_get_task_mon.return_value = mock_task_mon result = self.raid_service.clear_foreign_config('RAID.Integrated.1-1') self.conn.post.assert_called_once_with( '/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/' 'Actions/DellRaidService.ClearForeignConfig', data={'TargetFQDD': 'RAID.Integrated.1-1'}) self.assertEqual(mock_task_mon, result) def test_clear_foreign_config_no_config(self): mock_response = mock.Mock() mock_response.status_code = 400 mock_response.json.return_value = { "error": { "@Message.ExtendedInfo": [ { "Message": "No foreign configurations detected.", "MessageArgs": [], "MessageArgs@odata.count": 0, "MessageId": "IDRAC.2.5.STOR018", "RelatedProperties": [], "RelatedProperties@odata.count": 0, "Resolution": "If the only foreign drives present are " "in a secured locked state, run a " "secure erase operation on the drives " "to securely erase data or unlock these " "drives and retry the operation. " "Otherwise the operation was not " "successful because there are no " "foreign drives.", "Severity": "Warning" } ], "code": "Base.1.8.GeneralError", "message": "A general error has occurred. See ExtendedInfo " "for more information" } } no_config_error = exceptions.BadRequestError( 'POST', '/redfish/v1/Dell/Systems/System.Embedded.1/' 'DellRaidService/Actions/DellRaidService.ClearForeignConfig', mock_response) self.conn.post.side_effect = no_config_error result = self.raid_service.clear_foreign_config('RAID.Integrated.1-1') self.assertIsNone(result) def test_clear_foreign_config_bad_request(self): mock_response = mock.Mock() mock_response.status_code = 400 mock_response.json.return_value = { "error": { "@Message.ExtendedInfo": [ { "Message": "Controller not found.", "MessageArgs": [], "MessageArgs@odata.count": 0, "MessageId": "IDRAC.2.4.STOR030", "RelatedProperties": [], "RelatedProperties@odata.count": 0, "Resolution": "Provide a valid controller FQDD (Fully " "Qualified Device Descriptor) and retry " "the operation.", "Severity": "Warning" } ], "code": "Base.1.7.GeneralError", "message": "A general error has occurred. See ExtendedInfo " "for more information" } } no_config_error = exceptions.BadRequestError( 'POST', '/redfish/v1/Dell/Systems/System.Embedded.1/' 'DellRaidService/Actions/DellRaidService.ClearForeignConfig', mock_response) self.conn.post.side_effect = no_config_error self.assertRaises(exceptions.BadRequestError, self.raid_service.clear_foreign_config, 'RAID.Integrated.999') def test__get_task_monitor_from_dell_job(self): mock_task1 = mock.Mock(identity='JID_111222333444', path='/TaskService/Task/JID_111222333444') mock_task2 = mock.Mock(identity='JID_999888777666', path='/TaskService/Task/JID_999888777666') mock_tasks = mock.Mock() mock_tasks.get_members.return_value = [mock_task1, mock_task2] self.root.get_task_service.return_value.tasks = mock_tasks task_mon = self.raid_service._get_task_monitor_from_dell_job( self.mock_response) self.assertIsInstance(task_mon, taskmonitor.TaskMonitor) self.assertEqual('/TaskService/Task/JID_999888777666', task_mon.task_monitor_uri) def test__get_task_monitor_from_dell_job_location_missing(self): mock_response = mock.Mock() mock_response.status_code = 202 mock_response.headers = { 'Connection': 'Keep-Alive' } self.assertRaisesRegex( exceptions.ExtensionError, 'does not include Location', self.raid_service._get_task_monitor_from_dell_job, mock_response) def test__get_task_monitor_from_dell_job_task_not_found(self): mock_task1 = mock.Mock(identity='JID_000000000000', path='/TaskService/Task/JID_000000000000') mock_tasks = mock.Mock() mock_tasks.get_members.return_value = [mock_task1] self.root.get_task_service.return_value.tasks = mock_tasks self.assertRaisesRegex( exceptions.ExtensionError, 'not find task by id', self.raid_service._get_task_monitor_from_dell_job, self.mock_response) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/system/test_system.py0000664000175000017500000001206500000000000030345 0ustar00zuulzuul00000000000000# Copyright (c) 2021-2022 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy import exceptions from sushy_oem_idrac.resources.system import constants as sys_cons from sushy_oem_idrac.resources.system import raid_service from sushy_oem_idrac.resources.system import system as oem_system class SystemTestCase(BaseTestCase): def setUp(self): super(SystemTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'system.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 self.oem_system = oem_system.DellSystemExtension( self.conn, '/redfish/v1/Systems/System.Embedded.1') mock_perc_raid = mock.Mock( identity='Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1') type(mock_perc_raid).volumes = mock.PropertyMock( side_effect=exceptions.MissingAttributeError) mock_perc_nonraid = mock.Mock( identity='Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1', volumes=[mock.Mock(volume_type='rawdevice', raid_type=None)]) mock_boss_controller = mock.MagicMock(raid_types=['RAID1']) mock_boss_controller.name = 'BOSS-S1' mock_boss = mock.Mock(storage_controllers=[mock_boss_controller], drives=mock.Mock()) mock_perc_controller = mock.MagicMock(raid_types=['RAID1']) mock_perc_controller.name = 'PERC' mock_perc = mock.Mock(storage_controllers=[mock_perc_controller], drives=[mock_perc_raid, mock_perc_nonraid]) mock_system = mock.Mock() mock_storage_nocontroller = mock.Mock(storage_controllers=[]) mock_storage_nonraid = mock.Mock( storage_controllers=[mock.Mock(raid_types=[])]) mock_storage_boss = mock_boss mock_storage_raid = mock_perc mock_system.storage.get_members.return_value = [ mock_storage_nocontroller, mock_storage_nonraid, mock_storage_boss, mock_storage_raid] self.oem_system._parent_resource = mock_system def test_raid_service(self): with open('sushy_oem_idrac/tests/unit/json_samples/' 'raid_service.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 result = self.oem_system.raid_service self.assertEqual( '/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService', result.path) self.assertIsInstance(result, raid_service.DellRaidService) def test_change_physical_disk_state_raid(self): mock_taskmon = mock.Mock() mock_raid = mock.Mock() mock_raid.return_value = mock_taskmon mock_nonraid = mock.Mock() self.oem_system.raid_service.convert_to_raid = mock_raid self.oem_system.raid_service.convert_to_nonraid = mock_nonraid task_mons = self.oem_system.change_physical_disk_state( sys_cons.PhysicalDiskStateMode.RAID) self.assertEqual([mock_taskmon], task_mons) mock_raid.assert_called_once_with( ['Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1']) mock_nonraid.assert_not_called() def test_change_physical_disk_state_nonraid(self): mock_taskmon = mock.Mock() mock_raid = mock.Mock() mock_nonraid = mock.Mock() mock_nonraid.return_value = mock_taskmon self.oem_system.raid_service.convert_to_raid = mock_raid self.oem_system.raid_service.convert_to_nonraid = mock_nonraid task_mons = self.oem_system.change_physical_disk_state( sys_cons.PhysicalDiskStateMode.NONRAID) self.assertEqual([mock_taskmon], task_mons) mock_raid.assert_not_called() mock_nonraid.assert_called_once_with( ['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1']) def test_clear_foreign_config(self): mock_taskmon = mock.Mock() mock_clear_foreign_config = mock.Mock() mock_clear_foreign_config.side_effect = [mock_taskmon] self.oem_system.raid_service.clear_foreign_config =\ mock_clear_foreign_config task_mons = self.oem_system.clear_foreign_config() self.assertEqual([mock_taskmon], task_mons) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/taskservice/0000775000175000017500000000000000000000000026403 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/taskservice/__init__.py0000664000175000017500000000000000000000000030502 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/resources/taskservice/test_task.py0000664000175000017500000000535600000000000030767 0ustar00zuulzuul00000000000000# Copyright (c) 2021 Dell Inc. or its subsidiaries. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy.resources.taskservice import task as sushy_task from sushy_oem_idrac.resources.taskservice import constants as ts_cons from sushy_oem_idrac.resources.taskservice import task class TaskTestCase(BaseTestCase): def setUp(self): super(TaskTestCase, self).setUp() self.conn = mock.Mock() with open('sushy_oem_idrac/tests/unit/json_samples/' 'task.json') as f: mock_response = self.conn.get.return_value mock_response.json.return_value = json.load(f) mock_response.status_code = 200 self.task = sushy_task.Task( self.conn, '/redfish/v1/TaskService/Tasks/JID_257309938313') self.oem_task = task.DellTaskExtension( self.conn, '/redfish/v1/TaskService/Tasks/JID_257309938313') self.oem_task = self.oem_task.set_parent_resource( self.task, 'Dell') def test_parse_attributes(self): self.assertEqual('JID_257309938313', self.oem_task.identity) self.assertEqual('Configure: RAID.Integrated.1-1', self.oem_task.name) self.assertEqual('Job Instance', self.oem_task.description) self.assertIsNone(self.oem_task.completion_time) self.assertEqual('TIME_NA', self.oem_task.end_time) self.assertEqual(ts_cons.JobState.SCHEDULED, self.oem_task.job_state) self.assertEqual(ts_cons.JobType.RAID_CONF, self.oem_task.job_type) # For backward compability self.assertEqual(ts_cons.JOB_STATE_SCHEDULED, self.oem_task.job_state) self.assertEqual(ts_cons.JOB_TYPE_RAID_CONF, self.oem_task.job_type) self.assertEqual('Task successfully scheduled.', self.oem_task.message) self.assertEqual([], self.oem_task.message_args) self.assertEqual('IDRAC.2.5.JCP001', self.oem_task.message_id) self.assertEqual(0, self.oem_task.percent_complete) self.assertEqual('TIME_NOW', self.oem_task.start_time) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/test_asynchronous.py0000664000175000017500000000354500000000000026221 0ustar00zuulzuul00000000000000# Copyright (c) 2020 Dell Inc. or its subsidiaries. # # All Rights Reserved. # # 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. from unittest import mock from oslotest.base import BaseTestCase import sushy from sushy_oem_idrac.asynchronous import http_call class AsychronousTestCase(BaseTestCase): def setUp(self): super(AsychronousTestCase, self).setUp() self.conn = mock.Mock() def test_http_call_post_accepted(self): mock_post_response = self.conn.post.return_value mock_post_response.status_code = 202 mock_post_response.headers.get.return_value = '1' mock_get_202_response = mock.Mock() mock_get_202_response.status_code = 202 mock_get_202_response.headers.get.return_value = '1' mock_get_200_response = mock.Mock() mock_get_200_response.status_code = 200 self.conn.get.side_effect = [ mock_get_202_response, mock_get_200_response] resp = http_call(self.conn, 'POST') self.assertIs(resp, mock_get_200_response) def test_http_call_post_accepted_no_location(self): mock_response = self.conn.post.return_value mock_response.status_code = 202 mock_response.headers.get.return_value = None self.assertRaises(sushy.exceptions.ExtensionError, http_call, self.conn, 'POST') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/tests/unit/test_root.py0000664000175000017500000000326100000000000024444 0ustar00zuulzuul00000000000000# Copyright 2017 Red Hat, Inc. # All Rights Reserved. # # 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. import json from unittest import mock from oslotest.base import BaseTestCase from sushy import main class RootTestCase(BaseTestCase): @mock.patch('sushy.auth.SessionOrBasicAuth', autospec=True) @mock.patch('sushy.connector.Connector', autospec=True) @mock.patch('sushy.resources.sessionservice.sessionservice.' 'SessionService', autospec=True) def setUp(self, mock_session_service, mock_connector, mock_auth): super(RootTestCase, self).setUp() self.conn = mock.Mock() self.sess_serv = mock.Mock() self.sess_serv.create_session.return_value = (None, None) mock_session_service.return_value = self.sess_serv mock_connector.return_value = self.conn with open('sushy_oem_idrac/tests/unit/json_samples/root.json') as f: self.conn.get.return_value.json.return_value = json.load(f) self.root = main.Sushy('http://foo.bar:1234', verify=True, auth=mock_auth) def test_oem_vendors(self): self.assertEqual(['Dell'], self.root.oem_vendors) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac/utils.py0000664000175000017500000000221500000000000021437 0ustar00zuulzuul00000000000000# 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. import logging import time import sushy LOG = logging.getLogger(__name__) def reboot_system(system): if system.power_state != sushy.POWER_STATE_OFF: system.reset_system(sushy.RESET_FORCE_OFF) LOG.info('Requested system power OFF') while system.power_state != sushy.POWER_STATE_OFF: time.sleep(30) system.refresh() LOG.info('System is powered OFF') system.reset_system(sushy.RESET_ON) LOG.info('Requested system power ON') while system.power_state != sushy.POWER_STATE_ON: time.sleep(30) system.refresh() LOG.info('System powered ON') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8151398 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/0000775000175000017500000000000000000000000021417 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/PKG-INFO0000664000175000017500000000517100000000000022520 0ustar00zuulzuul00000000000000Metadata-Version: 2.1 Name: sushy-oem-idrac Version: 5.0.0 Summary: Dell EMC iDRAC OEM extension package for the sushy library Home-page: https://docs.openstack.org/sushy/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: UNKNOWN Description: Dell EMC OEM extension for sushy ================================ Sushy is a client [library](https://github.com/openstack/sushy) designed to communicate with [Redfish](https://en.wikipedia.org/wiki/Redfish_(specification)) based BMC. Redfish specification offers extensibility mechanism to let hardware vendors introduce their own features with the common Redfish framework. At the same time, `sushy` supports extending its data model by loading extensions found within its "oem" namespace. The `sushy-oem-idrac` package is a sushy extension package that aims at adding high-level hardware management abstractions, that are specific to Dell EMC BMC (which is known under the name of iDRAC), to the tree of sushy Redfish resources. Example use ----------- Once installed, sushy user can access Dell EMC OEM resources. For example, OEM extension of Manager resource can be instrumental for switching the node to boot from a virtual media device: ```python import sushy root = sushy.Sushy('http://mydellemcbmc.example.com') manager = root.get_manager('iDRAC.Embedded.1') oem_manager = manager.get_oem_extension('Dell') oem_manager.set_virtual_boot_device( sushy.VIRTUAL_MEDIA_CD, persistent=False, manager=manager) ``` See full example of virtual media boot setup in the [functional test suite](https://github.com/etingof/sushy-oem-idrac/blob/master/sushy_oem_idrac/tests/functional/vmedia_boot.py). Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Description-Content-Type: text/markdown ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/SOURCES.txt0000664000175000017500000000633000000000000023305 0ustar00zuulzuul00000000000000.stestr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.md babel.cfg requirements.txt setup.cfg setup.py test-requirements.txt tox.ini sushy_oem_idrac/__init__.py sushy_oem_idrac/asynchronous.py sushy_oem_idrac/constants.py sushy_oem_idrac/utils.py sushy_oem_idrac.egg-info/PKG-INFO sushy_oem_idrac.egg-info/SOURCES.txt sushy_oem_idrac.egg-info/dependency_links.txt sushy_oem_idrac.egg-info/entry_points.txt sushy_oem_idrac.egg-info/not-zip-safe sushy_oem_idrac.egg-info/pbr.json sushy_oem_idrac.egg-info/requires.txt sushy_oem_idrac.egg-info/top_level.txt sushy_oem_idrac/resources/__init__.py sushy_oem_idrac/resources/manager/__init__.py sushy_oem_idrac/resources/manager/constants.py sushy_oem_idrac/resources/manager/idrac_card_service.py sushy_oem_idrac/resources/manager/job_collection.py sushy_oem_idrac/resources/manager/job_service.py sushy_oem_idrac/resources/manager/lifecycle_service.py sushy_oem_idrac/resources/manager/manager.py sushy_oem_idrac/resources/system/constants.py sushy_oem_idrac/resources/system/raid_service.py sushy_oem_idrac/resources/system/system.py sushy_oem_idrac/resources/system/storage/constants.py sushy_oem_idrac/resources/system/storage/controller.py sushy_oem_idrac/resources/taskservice/constants.py sushy_oem_idrac/resources/taskservice/task.py sushy_oem_idrac/tests/__init__.py sushy_oem_idrac/tests/functional/__init__.py sushy_oem_idrac/tests/functional/vmedia_boot.py sushy_oem_idrac/tests/unit/__init__.py sushy_oem_idrac/tests/unit/base.py sushy_oem_idrac/tests/unit/test_asynchronous.py sushy_oem_idrac/tests/unit/test_root.py sushy_oem_idrac/tests/unit/json_samples/export_configuration_idrac.json sushy_oem_idrac/tests/unit/json_samples/export_configuration_nic_bios.json sushy_oem_idrac/tests/unit/json_samples/idrac_card_service.json sushy_oem_idrac/tests/unit/json_samples/job_collection_expanded.json sushy_oem_idrac/tests/unit/json_samples/job_service.json sushy_oem_idrac/tests/unit/json_samples/lifecycle_service.json sushy_oem_idrac/tests/unit/json_samples/manager.json sushy_oem_idrac/tests/unit/json_samples/manager_collection.json sushy_oem_idrac/tests/unit/json_samples/raid_service.json sushy_oem_idrac/tests/unit/json_samples/root.json sushy_oem_idrac/tests/unit/json_samples/storage_controller.json sushy_oem_idrac/tests/unit/json_samples/system.json sushy_oem_idrac/tests/unit/json_samples/task.json sushy_oem_idrac/tests/unit/resources/__init__.py sushy_oem_idrac/tests/unit/resources/manager/__init__.py sushy_oem_idrac/tests/unit/resources/manager/test_idrac_card_service.py sushy_oem_idrac/tests/unit/resources/manager/test_job_collection.py sushy_oem_idrac/tests/unit/resources/manager/test_job_service.py sushy_oem_idrac/tests/unit/resources/manager/test_lifecycle_service.py sushy_oem_idrac/tests/unit/resources/manager/test_manager.py sushy_oem_idrac/tests/unit/resources/system/__init__.py sushy_oem_idrac/tests/unit/resources/system/test_raid_service.py sushy_oem_idrac/tests/unit/resources/system/test_system.py sushy_oem_idrac/tests/unit/resources/system/storage/__init__.py sushy_oem_idrac/tests/unit/resources/system/storage/test_controller.py sushy_oem_idrac/tests/unit/resources/taskservice/__init__.py sushy_oem_idrac/tests/unit/resources/taskservice/test_task.py zuul.d/project.yaml././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/dependency_links.txt0000664000175000017500000000000100000000000025465 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/entry_points.txt0000664000175000017500000000061400000000000024716 0ustar00zuulzuul00000000000000[sushy.resources.manager.oems] dell = sushy_oem_idrac.resources.manager.manager:get_extension [sushy.resources.storage_controller.oems] dell = sushy_oem_idrac.resources.system.storage.controller:get_extension [sushy.resources.system.oems] dell = sushy_oem_idrac.resources.system.system:get_extension [sushy.resources.task.oems] dell = sushy_oem_idrac.resources.taskservice.task:get_extension ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/not-zip-safe0000664000175000017500000000000100000000000023645 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/pbr.json0000664000175000017500000000005600000000000023076 0ustar00zuulzuul00000000000000{"git_version": "da9a0e4", "is_release": true}././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/requires.txt0000664000175000017500000000006700000000000024022 0ustar00zuulzuul00000000000000pbr!=2.1.0,>=2.0.0 python-dateutil>=2.7.0 sushy>=4.0.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366240.0 sushy-oem-idrac-5.0.0/sushy_oem_idrac.egg-info/top_level.txt0000664000175000017500000000002000000000000024141 0ustar00zuulzuul00000000000000sushy_oem_idrac ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/test-requirements.txt0000664000175000017500000000100300000000000021003 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. coverage!=4.4,>=4.0 # Apache-2.0 python-subunit>=1.0.0 # Apache-2.0/BSD sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD openstackdocstheme>=1.18.1 # Apache-2.0 oslotest>=3.2.0 # Apache-2.0 stestr>=2.0.0 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT # releasenotes reno>=2.5.0 # Apache-2.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/tox.ini0000664000175000017500000000424400000000000016067 0ustar00zuulzuul00000000000000[tox] minversion = 3.18.0 envlist = py3,pep8 skipsdist = True ignore_basepython_conflict=true [testenv] usedevelop = True install_command = pip install {opts} {packages} basepython = python3 setenv = VIRTUAL_ENV={envdir} PYTHONWARNINGS=default::DeprecationWarning deps = -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt commands = stestr run --slowest {posargs} [testenv:pep8] deps = hacking>=4.1.0,<5.0.0 # Apache-2.0 flake8-import-order>=0.17.1 # LGPLv3 pycodestyle>=2.0.0,<3.0.0 # MIT commands = flake8 {posargs} [testenv:venv] commands = {posargs} [testenv:cover] setenv = {[testenv]setenv} PYTHON=coverage run --source sushy_oem_idrac --omit='*tests*' --parallel-mode # After running this target, visit sushy_oem_idrac/cover/index.html # in your browser, to see a nicer presentation report with annotated # HTML listings detailing missed lines. commands = coverage erase stestr run {posargs} coverage combine coverage report --omit='*tests*' coverage html -d ./cover --omit='*tests*' coverage xml -o cover/coverage.xml --omit='*tests*' [testenv:docs] commands = python setup.py build_sphinx [testenv:releasenotes] commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [testenv:debug] commands = oslo_debug_helper -t sushy_oem_idrac/tests {posargs} [flake8] # E123, E125 skipped as they are invalid PEP-8. # [W503] Line break before binary operator. show-source = True ignore = E123,E125,W503 # [H106] Don't put vim configuration in source files. # [H203] Use assertIs(Not)None to check for None. # [H204] Use assert(Not)Equal to check for equality. # [H205] Use assert(Greater|Less)(Equal) for comparison. # [H210] Require 'autospec', 'spec', or 'spec_set' in mock.patch/mock.patch.object calls # [H904] Delay string interpolations at logging calls. enable-extensions=H106,H203,H204,H205,H210,H904 builtins = _ exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build import-order-style = pep8 application-import-names = sushy_oem_idrac filename = *.py ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1662366240.8311398 sushy-oem-idrac-5.0.0/zuul.d/0000775000175000017500000000000000000000000015771 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1662366199.0 sushy-oem-idrac-5.0.0/zuul.d/project.yaml0000664000175000017500000000016500000000000020325 0ustar00zuulzuul00000000000000- project: templates: - check-requirements - openstack-cover-jobs - openstack-python3-zed-jobs