Giter Site home page Giter Site logo

dmtf / redfish-interface-emulator Goto Github PK

View Code? Open in Web Editor NEW
56.0 31.0 24.0 2.51 MB

The Redfish Interface Emulator can emulate a Redfish-based interface statically (GET) or dynamically (POST, PATCH, DELETE)

License: Other

Python 97.70% HTML 2.17% Dockerfile 0.13% Procfile 0.01%
redfish

redfish-interface-emulator's Introduction

Copyright 2016-2023 DMTF. All rights reserved.

Redfish Interface Emulator

The Redfish Interface Emulator that can emulator a Redfish interface resources as static or dynamically.

Static emulator is accomplish by copy a Redfish mockup in a ./static directory.

Dynamic emulator is accomplished by creating the Python files. The code for an example resource (EgResource) is available to expedite the creation of dynamic resources. The example is for a collection/member construct, EgResources/{id}.

The Swordfish model has been emulate using this emulator. The repository is available at Swordfish API Emulator. The repository provides a good example of the Python files for dynamic resources.

The program has been verified on 3.5.2 and 3.9.1. Use the packet sets to install the correct packages.

The emulator is structure so it can be ran locally, in a Cloud Foundry, or as a Docker file.

Execute Locally

When executing the Emulator locally, the Redfish service appears at port 5000, by default. The Redfish client uses the following URL to access the emulator Redfish server - http://localhost:5000. To run a second instance must a different 'port'. The port number can be changed via the command line parameters or the config.json file.

Package Installation

Several external packages are required for this tool. You may install the prerequisites by running:

pip3 install -r requirements.txt

Invocation

Edit the emulator-config.json file and set "MODE": "Local", then start the emulator.

python emulator.py

Execute on a Cloud Foundry

The cloud foundry method has be successful within a company internal cloud foundry service. It has not be attempted on a public cloud foundry service.

Package Installation

The required python packages for a Cloud Foundry environment are listed in the file ./requirements.txt. The file lists the Python package, without the revision. The packages will be installed automatically during invocation.

The cloud foundry makes use of the following files: requirements.txt, runtime.txt, and Profile. So they should exists in the same directory as emulator.py.

Invocation

Edit the emulator-config.json file and set "MODE": "Cloud", then push the emulator to the foundry.

cf push [foundry-app-name]

The foundry-app-name determines the URL for the Redfish service.

Execute via Docker

Installation

Use one of these actions to pull or build the container:

  • Pull the container from Docker Hub:

    docker pull dmtf/redfish-interface-emulator:latest
  • Build a container from local source. Make sure to run from the root directory of the code that contains the Dockerfile:

    docker build -t dmtf/redfish-interface-emulator:latest .
  • Build a container from GitHub:

    docker build -t dmtf/redfish-interface-emulator:latest https://github.com/DMTF/Redfish-Interface-Emulator.git

Invocation

This command runs the container with the built-in mockup:

docker run --rm dmtf/redfish-interface-emulator:latest

Configuring the Emulator

The behavior of the emulator can be control via command line flags or property values in emulator-config.json.

Emulator app flags

The emulator is invoked with the following command:

python emulator.py [-h] [-v] [-port PORT] [-debug]
-h -- help (gives syntax and usage) 
-v -- verbose
-port -- specifies the port number to use
-debug -- enables debugging (needed to debug flask calls)

Format of emulator-config.json

The emulator reads the emulator-config.json file to configure its behavior.

{
    "MODE": "Local"
    "HTTPS": "Disable",
    "SPEC": "Redfish",
    "STATIC": "Enable",
    "TRAYS": [
        "./Resources/Systems/1/index.json"
    ]
    "POPULATE": "Emulator"
}
  • The MODE property specifies port to use. If the value is 'Cloud', the port is assigned by the cloud foundry. If the value is ‘Local’, the port is assigned the value of the port parameter is the command line or 5000, by default. (e.g. localhost:5000/redfish/v1)
  • The HTTPS property specifies whether HTTP or HTTPS will used by the client
  • The STATIC property specifies whether the emulator runs with the mockups in ./api_emulator/redfish/static
  • The SPEC property specifies whether the computer system is represented as a Redfish ComputerSystem (SPEC = “Redfish”) or another schema.
  • The TRAYS property specifies the path to the resources that will make up the initial resource pools. These simple resource pools are depleted as computer systems are composed. Multiple trays can be specified.
  • The POPULATE property specifies the path to the file used by the INFRAGEN module to populate the Redfish Interface backend. If the file does not exist or if POPULATE is not defined, the emulator will start empty.

Three sample configuration files are provided:

  • emulator-config_static.json (default) - start emulator with the static mockup
  • emulator-dontpopulate.json - start emulator with no chassis or systems
  • emulator-populate.json - start emulator and populate with infragen

HTTPS

The emulator supports HTTP and HTTPS connections. HTTPS is enabled by setting the HTTPS property in emulator-config.json.

{
    "HTTPS": "Enable",
	...
}

When HTTPS is enabled, the emulator looks for the files: server.crt and server.key in the same directory as emulator.py. The certificate file and key file can be self-signed or obtained from a certificate authority.

Static emulation of a mockup

The emulator can be used to support static mockups. In a static mock, only HTTP GETs will work. Other Redfish simulators support static mockups.

The static mockup is found in the directory ./api_emulator/redfish/static. The emulator comes with a sample Redfish mockup already in the directory. This can be replaced with any mockup folder hierarchy. The Redfish Forum has posted several of their mockups in DSP2043.

Note: If the new mockup has additional resources in the ServiceRoot, then modifications need to be made in static_resource_emulator.py to adds these new resources.

Dynamic emulation

The emulator was designed to support dynamic resources. This requires that Python code exists for each dynamic resource. Resources which are static and dynamic can co-exist in an emulator. This means one can straddle static vs dynamic emulation, with some resources static while others are dynamic.

Dynamic resource implementations which have been implemented are provided in the Appendix.

The following outlines the overall process. More complete documentation is in a Word document in the ./doc directory. To expedite the creation of the API-file and template file, the code generators for both files are described.

Manually creating a dynamic resource

A dynamic resource is made by creating a template-file and an API-file for the resource.

  • The template-file contain the properties of the resource. The file is used when a new instance of the resource is created.
  • The API-file contain the behavior of the resource for each HTTP command. If there is an associated collection resource, the file also contains the behavior of the collection resource.

Once the files are created, they are placed in the emulator directory structure.

  • The template-file is placed in the directory ./api_emulator/Redfish/template
  • The API-file is placed in the directory ./api_emulator/Redfish
  • If the resource in the Service Root, the the emulator.py file needs to be edited.
    • If the dynamic resource replaces a static resource, then replace the line which loads the static mockup with the line to add to dynamic resource API.

Auto-generate the API file

To generate a API file, execute the following command

codegen_api [mockup] [outputdir]

Where

  • [mockup] is the name of the singleton resource
  • [outputdir] is the directory for the API file
  • The command uses the index.json file in the current work directory as input

The generated code supports the HTTP GET, PATCH, POST and DELETE commands

If the resource has subordinate resources that need to be instantiated when this resource is instantiated, that code will need to be manually added.

Auto-generate the template file

To generate a template file, execute the following command

codegen_template [mockup] [outputdir]

Where

  • [mockup] is the name of the singleton resource
  • [outputdir] is the directory for the API file
  • The command uses the index.json file in the current work directory as input

(TODO - add the filename as a command line parameter)

The codegen_template source file contains a dictionary with the names of Redfish collections and their corresponding wildcard. This dictionary needs to be manually updated to the keep in sync with Redfish modeling.

Auto-populating the dynamic emulator

Once a resource is made dynamic, the emulator can either start up with no members in its collections or some initial set of members.

To populate the Redfish model, set the POPULATE property in emulator-config.json.

{
    "POPULATE": "Emulator",
	. . .
}

Once the emulator has started, it will read the file ./infragen/populate-config.json. This file contains a JSON structure which specifies resources to populate. The following example specifies that 5 Chassis be instantiated and linked to 5 Systems.

{
  "POPULATE": {
    "Chassis": [
      {
        "Name": "Compute Chassis",
        "Id": "Chassis-{0}",
        "Count": 5,
        "Links": {
          "ComputerSystems": [
            {
              "Name": "Compute System",
              "Id": "System-{0}",
              "Count": 1,
              "Processors": [
                {
                  "Id": "CPU{0}",
                  "TotalCores": 12,
                  "MaxSpeedMHz": 2400,
                  "Count": 2
                }
              ],
              "Memory": [
                {
                  "Id": "DRAM{0}",
                  "CapacityMiB": 16384,
                  "MemoryType": "DRAM",
                  "Count": 4
                },
                {
                  "Id": "NVRAM{0}",
                  "CapacityMiB": 65536,
                  "MemoryType": "NVDIMM_N",
                  "Count": 4
                }
              ],
              "SimpleStorage": [
                {
                  "Id": "SAS-CTRL{0}",
                  "Count": 1,
                  "Devices": {
                    "CapacityBytes": 549755813888,
                    "Count": 1
                  }
                }
              ],
              "EthernetInterfaces": [
                {
                  "Id": "NIC-{0}",
                  "SpeedMbps": 10000,
                  "Count": 2
                }
              ]
            }
          ]
        }
      },

INFRAGEN module

The INFRAGEN module is used to populate the Redfish Interface with members (Chassis, Systems, Resource Blocks, Resources Zones, Processors, Memory, etc).

This module is execute by emulator.py once the emulator is up and reads the populate-config.json file.

The tool generate_template.py can be used to help a user with the creation of JSON template according to a specific Redfish schema by guiding the user through the schema and asking for input values. This module runs independently of the populate function and from the emulator itself.

Testing the (dynamic) Emulator

The following is the general command for running unit test.

python unittests.py <SPEC> "<PATH>"

Where

  • should correspond to the value in emulator-config.json
  • is the path to use for testing and should be enclosed in double-quotes
  • Example: python unittests.py Redfish "localhost:5000"

Once the command completes, inspect the log file which is produced, "test-rsa-emulator.log".

The command to test the emulator can executed against the emulator running locally or hosted in the cloud.

Composition GUI

Generally, Postman is used to interact with the Redfish interface. However, a web GUI is available for testing the composition service, including the ability to compose and delete systems.

  • Compose
    • Navigate to /CompositionService/ResourceZones/<ZONE>/, a check box appears next to each Resource Block
    • Select the Resource Blocks to use to compose a system
    • Press the button "compose" on the top of the webpage
  • Delete
    • Navigate the browser to /Systems/<SYSTEM>/, if the system is of type "COMPOSED", a "delete" button appears
    • Select the delete button and the composed system will be deleted

Screenshots of the browser available in /doc/browser-screenshots.pdf

To use, point a brower to the URI http://localhost:5000/browse.html

Release Process

Run the release.sh script to publish a new version.

sh release.sh <NewVersion>

Enter the release notes when prompted; an empty line signifies no more notes to add.

Appendix - Available Dynamic Resources implementations

The emulator is made dynamic by added python code to emulate a resources RESTful behavior, call the API-file.

Dynamic resources implementations can be found in the Redfish Interface Emulator repository and the SNIA API Emulator repository.

The repository also had the codegen_api code generator for creating an API-file for a resource with some default behaviors. The code generator takes a mockup file as input.

Redfish Interface Emulator

The Redfish Interface Emulator comes with a small set of API-files to demonstrate the code structure. The repository also had the codegen_api code generator for creating an API-file for a resource with some default behaviors. The code generator takes a mockup file as input.

These dynamic resources are available in the Redfish Interface Emulator repository in the api_emulator/redfish directory.

Resource API-file
./CompositionService CompositionService_api.py
./EventService event_service.py
./SessionService
./SessionService/Sessions/{id} sessions_api.py
./Chassis/{id} Chassis_api.py
./Chassis/{id}/Thermal thermal_api.py
./Chassis/{id}/Power power_api.py
./Systems/{id} ComputerSystem_api.py
./Systems/{id}/Memory memory.py
./Systems/{id}/Processors/{id} processor.py
./Systems/{id}/SimpleStorage/{id} simple_storage.py
./Managers/{id} Manager_api.py

SNIA API Emulator

The Swordfish API Emulator added the API-files to emulate the Swordfish schema.

These dynamic resources are available in the SNIA API Emulator repository in the api_emulator/redfish directory.

API-file Resource
. serviceroot_api
./EventService/Subscriptions Subscriptions.py
./Chassis/{id} Chassis_api.py
./Chassis/{id}/Memory c_memory
./Chassis/{id}/Drives/{id} drives_api.py
./Chassis/{id}/MediaController MediaControllers_api.py
./Chassis/{id}/MediaControllers/{id}/Ports mc_ports_api.py
./Chassis/{id}/NetworkAdapters networkadapaters_api.py
./Chassis/{id}/NetworkAdapters/{id}/NetworkDeviceFunctions/{id} networkdevicefunctions_api.py
./Chassis/{id}/NetworkAdapters/{id}/Ports/{id} nwports_api.py
./Systems/{id} ComputerSystem_api.py
./Systems/{id}/Storage/{id}/Volumes/{id} volumes_api
./Systems/{id}/Storage/{id}/StoragePools/{id} storagepools_api.py
./Systems/{id}/Memory/{id} memory.py
./Systems/{id}/Memory/{id}/MemoryDomains/{id} memory_domains_api.py
./Systems/{id}/Memory/{id}/MemoryDomains/{id}/MemoryChunks/{id} md_chunks_api.py
./Fabrics/{id}/Connections/{id} f_connections.py
./Fabrics/{id}/EndpointGroups/{id} f_endpointgroups.py
./Fabrics/{id}/Endpoints/{id} f_endpoints.py
./Fabrics/{id}/Switches/{id} f_switches.py
./Fabrics/{id}/Switches/{id}/Ports/{id} f_switch_ports_api.py
./Fabrics/{id}/Zones/{id} f_zones_api.py
./Fabrics/{id}/FabricAdapters/{id} fabricadapters.py
./Fabrics/{id}/FabricAdapters/{id}/Ports/{id} fa_ports_api.py
./Storage storage_api.py
./Storage/{id}/Controllers/{id} storagecontrollers_api
./Storage/{id}/FileSystems filesystems_api.py
./Storage/{id}/StorageGroups storagegroups_api.py
./StorageSystems/{id} storagesystems_api.py
./StorageServices/{id}/ClassesOfService classofservice_api.py
./StorageServices/{id}/DataProtectionLoSCapabilities dataprotectionloscapabilities_api.py
./StorageServices/{id}/DataSecurityLoSCapabilities datasecurityloscapabilities_api.py
./StorageServices/{id}/DataStorageLoSCapabilities datastorageloscapabilities_api.py
./StorageServices/{id}/EndpointGroups EndpointGroups_api.py
./StorageServices/{id}/Endpoints Endpoints_api.py
./StorageServices/{id}/IOConnectivityLoSCapabilities IOConnectivityLOSCapabilities_api.py
./StorageServices/{id}/IOPerformanceLoSCapabilities IOPerformanceLOSCapabilities_api.py

redfish-interface-emulator's People

Contributors

billdodd avatar dependabot[bot] avatar felipeportella avatar ghernadi avatar hughsie avatar jautor avatar jazzliz avatar jcleung5549 avatar mgazz avatar mraineri avatar pwvancil avatar rahlvers avatar rainbowmango avatar stmcginnis avatar xahmad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redfish-interface-emulator's Issues

unittests.py was broken

The file unittests.py has two minor Python syntax issues raised if we try to run it:

  1. File "unittests.py", line 62
    logger.info('PASS: GET of {0} successful (response below)\n {1}'.format(getting, r.text))
    ^
    TabError: inconsistent use of tabs and spaces in indentation

  2. File "unittests.py", line 156
    print'Testing interface at:', sys.argv[2]
    ^
    SyntaxError: invalid syntax

Singleton POST command fails to add new resource instances created from templates

Many of the dynamic resources in the emulator are supposed to support emulator-only singleton POST commands that create new resource instances from pre-defined templates. These POST commands currently fail, due to a conflict with the way Infragen was added to the emulator.

Infragen uses the emulator’s internal method calls in dynamic resources instead of the Redfish API, and by itself this might have been OK, but in many cases the merged Infragen code made changes to the methods themselves in dynamic resources. These changes are causing failures for the POST commands that are supposed to create new instances from pre-defined templates.

There is no easy way to fix this problem. If the singleton POST commands are fixed to work as originally intended, Infragen will break. If the emulator is left the way it is, the ability to add new instances from pre-defined templates will remain broken. A reasonable solution would be to fix the emulator to work as originally intended, and to revise Infragen to work via the Redfish API instead of using the emulator’s internal method calls.

Clarify how to enable HTTPS

Describe that enabling HTTPS, requires the key and cert files to exist in the execution directly - specifically named server.key and server.cert.

Trouble using "/" at the end of a URI

Using a "/" at the end of a URI makes a difference with the emulator, depending upon whether it is for a leaf node (one at the edge of the tree) or a non-leaf node (one inside the tree).

For example, this is what happens when accessing a leaf node:

GET http://localhost:5000/redfish/v1/Systems/CS_5 results in a 200 OK response and produces reasonable output, but...

GET http://localhost:5000/redfish/v1/Systems/CS_5/ gets a 500 Internal Server Error response and the emulator console reports an exception originating in emulator.py.

However, this is what happens when accessing a non-leaf node:

GET http://localhost:5000/redfish/v1/Systems results in a 301 Moved Permanently response, and...

GET http://localhost:5000/redfish/v1/Systems/ results in a 200 OK response and produces reasonable output.

Note that the emulator behavior is different for getting a 200 OK response, depending upon whether the URI is for a leaf node or a non-leaf node.

This behavior is made more obvious by the Chrome Restlet Client extension. By default, Restlet does not automatically follow redirects, so if you leave the trailing "/" off for a non-leaf node, you'll get a 301 Moved Permanently response. Using the same URI with a trailing "/" (or telling Restlet to follow redirects) gets a 200 OK response. But having a trailing "/" on a leaf node causes an exception.

The Chrome Advance REST Client (ARC) seems to silently follow redirects, so there's no obvious difference between having or not having a trailing "/" on a URI for a non-leaf node. But having a trailing "/" on a leaf node still causes an exception.

Should the emulator be showing these differences between having and not having a trailing "/" on URIs?

URL behaviors are different for static and dynamic resources

Using the Restlet Client, which does not do automatic redirection, the URLs that must be used for accessing static and dynamic emulator resources are different.

Dynamic resources must be accessed with URLs that do NOT end with a "/" character. If the URL for a dynamic resource ends with a "/" character, the emulator gives a "500 INTERNAL SERVER ERROR" response.

Static resources must be accessed with URLS that DO end with a "/" character. If the URL for a static resource does NOT end with a "/" character, the emulator gives a "301 MOVED PERMANENTLY" response, which is a redirect.

Collection POST commands fail to add new resource instances to non-ComputerSystem resource/subresource collections

It should be possible to add new resources to many Redfish collections by doing a POST command to the collection. This currently works for the emulator's Chassis dynamic resource, but it fails for the rest of the emulator’s current set of dynamic resources.

Note: A similar problem with the ComputerSystem collection was reported separately (see #44 ), where the problems seem to be strongly tied to the way Infragen was implemented. The problem being reported here is for the other (non-ComputerSystem) dynamic resources, since it looks like they can be fixed without impacting the way Infragen currently works.

Python dependency files need to be made consistent

There are four files that talk about Python dependencies, but they do not agree with each other:
(1) dependencies/Python Packages to place in directory.txt
(2) install.py
(3) installing_dependencies.txt
(4) requirements.txt

It would be good to have at least the requirements.txt file brought up-to-date with what is currently needed. Here is a list of packages that work for stand-alone operation on Windows (I'm not sure about the list of packages needed for other situations):
setuptools
markupsafe
itsdangerous
flask
aniso8601
pytz
flask_httpauth
requests
flask_restful
StringGenerator==0.2.1
urllib3

The version of StringGenerator is specified in this list because the latest version of StringGenerator (0.3.0) does not install on my Windows system.

If the other files that talk about Python dependencies are also still needed, they should be made to be consistent with an updated requirements.txt file.

ServiceEnabled boolean being returned as a string

There are several objects that have a ServiceEnabled boolean property. Most are correctly returning this as it's defined as a boolean, but the following are returning the string "true" instead:

  • EventService
  • CompositionService
  • Manager

Getting /redfish/v1/Systems results in "Internal System Error"

(From Don Deel) Everything looks good at first. Using a browser (or the Restlet Client in Chrome) I can see the Redfish service root and access things like the Chassis and Managers collections. But no matter what I do, attempting to access Systems results in an “Internal Server Error” message. The emulator itself keeps running, the same way it would if I simply mis-typed something.

How to change the ComputerSystem.Status property when performing a ResetAction

The emulation code for the ./Systems/{id}/ResetAction resource in located in the file ./api_emulator/redfish/ComputerSystem/ResetAction.py. A behavior of a reset action is to change the ComputerSystem.Status.State property. However, this requires the code import a module within the ComputerSystem.py code in the parent directory. Python 3.3 removed relative imports, so imports from a parent directory requires hacking PYTHONPATH or adding the parent-path to sys.path.

There is a request for a cleaner way.

Collection POST command fails to add a resource instance to the ComputerSystem collection

A POST command to add a new instance to the ComputerSystem collection fails with an error message that says “KeyError: ‘Links’”. This happens no matter what is in the body of the POST command.

After reviewing the pull request history (see #16 ), this appears to be a consequence of the way support for composed systems was added to the ComputerSystem dynamic resource. Perhaps that work was not completed?

GET on EventService works, but causes an error

Running the unmodified code from master, the emulator outputs an error on the console whenever EventService is accessed with a normal GET:

GET http://localhost:5000/redfish/v1/EventService

The Restlet Client receives a "200 OK" result and an OK-seeming Body from this GET, but the following traceback and error message appears on the console:

Traceback (most recent call last):
File "C:\Users\ddon\Documents\EmRf\api_emulator\redfish\EventService_api.py", line 33, in init
g.api.add_resource(SubscriptionCollectionAPI, '/redfish/v1/EventService/Subscriptions')
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask_restful_init_.py", line 404, in add_resource
self.register_view(self.app, resource, *urls, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask_restful_init
.py", line 470, in _register_view
app.add_url_rule(rule, view_func=resource_func, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask\app.py", line 64, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask\app.py", line 1051, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: subscriptioncollectionapi

Issues with Using Created Mockup to use Static Emulator

I created my own mockup with a live redfish service from the Redfish-Mockup-Creator and Redfish-Mockup-Server runs as expected. However, when I follow the instructions to use my own mockup with the Redfish-Interface-Emulator it doesn't see my mockup that I'm trying to use. Replacing the \api_emulator\redfish\static directory with my mockup doesn't work. The readme and instructions found in /doc seem to be a little inconsistent, and I'm trying to find out what I'm doing wrong.

FileNotFoundError: [Errno 2] No such file or directory: 'Flask-RESTful-0.3.1.zip'

I got the following error when I run install.py
FileNotFoundError: [Errno 2] No such file or directory: 'Flask-RESTful-0.3.1.zip'


I installed Flask-RESTful-0.3.1 using pip, which gives the following error;
No matching distribution found for Flask-RESTful-0.3.1

if I use "pip install -r requirements.txt" command, it adds the following directory:
/usr/lib64/python3.6/site-packages/flask_restful
its version is 3.6.
and it does not contain any zip file.

I also checked:
https://github.com/flask-restful/flask-restful
It does not contain version 0.3.1

Need hurdle/regression test suite

Create a rendition of unittest.py to act as hurdle/regression for changes to the emulator. It should test the basic functionality:

  • GET a resource (collection and singleton)
  • PATCH a resource (collection and singleton)
  • POST to a collection resource (to create a new singleton)
  • DELETE a singleton resource
  • Perform on Chassis, Systems, Managers

The odataType of Power

Hello,
I visite the "Chassis/{ChassisId}/Power" URL and find that the "@odata.type" is "#Power.v1_0_0.PowerMetrics", perhaps it should be "#Power.v1_0_0.Power"
Thank you.

Malformed Status struct in several objects

The Status struct is defined as being:

{ "Health": "Ok", "HealthRollup": "Ok", "Oem": "foo", "State": "Enabled" }

http://redfish.dmtf.org/schemas/v1/Resource.json

There are several emulated objects that incorrectly introduce an additional layer of a "State" key for the status the looks like:

{ "State": { "Health": "Ok", "HealthRollup": "Ok", "Oem": "foo", "State": "Enabled" } }

The following are examples of this incorrect format:

  • ethernetinterfaces
  • memory
  • simplestorage

All of these are defined as having a Status property of type Status.

Correct examples can be found in:

  • processor
  • thermal
  • power

And several other locations.

Remove emulator_ssl.py

The HTTPS functionality in this file was added to emulator.py. The functionality is controlled by the HTTPS property in emulator-config.json. Hence this file should be remove to avoid confusion.

curl POST request getting a 404 not found return from emulator.py

Both my IBM CentOS server and my local wsl CentOS image are both getting a 404 return on a POST request. It is happening with both http and https requests. I would think the problem may be in the flask module or maybe requests.

Client side:

(venv) [root@IBM-R912JTS2 emulator]# curl -X POST -k -H 'Content-Type: application/json' https://9.114.207.147:5000/redfish/v1/SessionService/Sessions -d '{"UserName":"Admin"}'
curl: (7) Failed to connect to 9.114.207.147 port 5000: Connection refused
(venv) [root@IBM-R912JTS2 emulator]# clear
(venv) [root@IBM-R912JTS2 emulator]# curl -X POST -k -H 'Content-Type: application/json' https://172.24.225.83:5000/redfish/v1/SessionService/Sessions -d '{"UserName":"Admin"}'
""(venv) [root@IBM-R912JTS2 emulator]# curl -X GET -H 'Content-Type: application/json' https://172.24.225.83:5000/redfish/v1/
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
(venv) [root@IBM-R912JTS2 emulator]# curl -k -X GET -H 'Content-Type: application/json' https://172.24.225.83:5000/redfish/v1/
{
"@odata.context": "/redfish/v1/$metadata#ServiceRoot",
"@odata.type": "#ServiceRoot.1.0.0.ServiceRoot",
"@odata.id": "/redfish/v1/",
....

Server side:

(venv) [root@IBM-R912JTS2 emulator]# python3 emulator.py
/mnt/c/Users/C-VS95897/venv/lib64/python3.6/site-packages/requests/init.py:104: RequestsDependencyWarning: urllib3 (1.26.9) or chardet (5.0.0)/charset_normalizer (2.0.12) doesn't match a supported version!
RequestsDependencyWarning)
INFO:root:Mockup folders
['Redfish']

  • Redfish endpoint at localhost:5000
  • Using static mockup
    INFO:root:Init ResourceDictionary.
    INFO:root:Loading Redfish static resources
    INFO:root:Init ResourceDictionary.
  • Use HTTPS
  • Running in Redfish mode
  • Serving Flask app 'g' (lazy loading)
  • Environment: production
    WARNING: This is a development server. Do not use it in a production deployment.
    Use a production WSGI server instead.
  • Debug mode: off
    WARNING:werkzeug: * Running on all addresses.
    WARNING: This is a development server. Do not use it in a production deployment.
    INFO:werkzeug: * Running on https://172.24.225.83:5000/ (Press CTRL+C to quit)
    INFO:werkzeug:172.24.225.83 - - [05/Jul/2022 10:57:23] "POST /redfish/v1/SessionService/Sessions HTTP/1.1" 404 -
    INFO:werkzeug:172.24.225.83 - - [05/Jul/2022 10:58:40] "GET /redfish/v1/ HTTP/1.1" 200 -

Using for static mockups

I am really new to this so please be kind...
I am seeing the following error when I try to start the Emulator "Traceback (most recent call last):
File "emulator.py", line 20, in
import g
File "/data/Redfish-Interface-Emulator/g.py", line 11, in
from flask import Flask
ImportError: No module named flask"

Any guidance would be appreciated!
Thanks.

how to change this populate-config.json file based on my requirements?

how to change this populate-config.json file based on my requirements?

Chassis Count -1 Cartridge Count -12 or 24 (Server , storage,NIC,FPGA ,GPU) Each Cartridge node count -2 or 4 (if cartridge is server) SwitchCard count -2 Each SwitchCard Device count -2 (Storage ,NIC ,FPGA,GPU)

Errors in error handling for getting invalid resource

If a request to a resource is made that is invalid or no longer there, looking up the resource will hit a KeyError. This should be fine, but the error handling for this attempts to get the exception information by accessing the 'message' property. Not all exceptions have a message property, including KeyError, so this causes the following:

Traceback (most recent call last):
File "emulator.py", line 180, in get
config = self.get_configuration(resource_manager, path)
File "emulator.py", line 282, in get_configuration
raise PathError("Resource not found: " + str(e.message))
AttributeError: 'KeyError' object has no attribute 'message'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/smcginnis/repos/SNIA/Swordfish/venv/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/smcginnis/repos/SNIA/Swordfish/venv/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functionsrule.endpoint
File "/Users/smcginnis/repos/SNIA/Swordfish/venv/lib/python3.7/site-packages/flask_restful/init.py", line 458, in wrapper
resp = resource(*args, **kwargs)
File "/Users/smcginnis/repos/SNIA/Swordfish/venv/lib/python3.7/site-packages/flask/views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "/Users/smcginnis/repos/SNIA/Swordfish/venv/lib/python3.7/site-packages/flask_restful/init.py", line 573, in dispatch_request
resp = meth(*args, **kwargs)
File "emulator.py", line 189, in get
resp = INTERNAL_ERROR_Get
NameError: name 'INTERNAL_ERROR_Get' is not defined

In addition to the e.message issue, there appears to be a typo with INTERNAL_ERROR_Get. We only have an INTERNAL_ERROR variable defined, and it would appear this is what is supposed to be used there.

sample redfish emulator implementing .is it correct?

from flask import Flask
from flask_restful import Resource, Api
import sys, traceback
import copy
import strgen
from utils import replace_recurse

from Acclipc.mdc_webtask import *

BASE_PATH = "/redfish/v1/"

app = Flask(name)
api = Api(app)

class ResourceCollection(Resource):
def init(self):
self.rest_base = BASE_PATH
self.uuid = ""

def get(self):
	"""
	Configuration property - Service Root
	"""
	config = {
		'@odata.context': self.rest_base + '$metadata#ServiceRoot',
		'@odata.type': '#ServiceRoot.1.0.0.ServiceRoot',
		'@odata.id': self.rest_base,
		'Id': 'RootService',
		'Name': 'Root Service',
		'ServiceVersion': '1.0.0',
		'UUID': self.uuid,
		'Links': {
			'Chassis': {'@odata.id': self.rest_base + 'Chassis'}
		}
	}

	return config

class Chassis(Resource):

def __init__(self):
	self.rb = BASE_PATH
	self.config = {
		'@odata.context': self.rb + '$metadata#ChassisCollection.ChassisCollection',
		'@odata.id': self.rb + 'Chassis',
		'@odata.type': '#ChassisCollection.1.0.0.ChassisCollection',
		'Name': 'Chassis Collection',
		'[email protected]': 1,
		'Member' : self.rb + 'Chassis/Chassis-1',
		}	
		
def get(self):
	try:
		resp = self.config, 200
	except Exception:
		traceback.print_exc()
		resp = INTERNAL_ERROR
	return resp

class Chassisinfo(Resource):

def __init__(self):
	self.rb = BASE_PATH
	self.config = {
		"@odata.context": self.rb +"$metadata#Chassis.Chassis",
		"@odata.id": self.rb + "Chassis",
		"@odata.type": "#Chassis.v1_0_0.Chassis",
		'Name': 'MDC System Chassis',
		"ChassisType": "RackMount",
		"SerialNumber": "",
		"PartNumber": "",
		"MaxPower": "",
		"Chassis ID": "",
		"AssetTag": "",
		"Oem": {
			"Links": {
				"Cartridge": [ 
					{
						"@odata.id": self.rb +"Chassis/Chassis-1/Cartridge"
					}
				],
				"Switch": [ 
					{
						"@odata.id": self.rb +"Chassis/Chassis-1/Switch"
					}
				]
			}
		}
		}
		
def get(self,ident):
	global wildcards
	res = login("accl","accl")
	result = chassisinfo()
	self.config['@odata.id']= self.rb + ident
	self.config['PartNumber']= result[0]
	self.config['SerialNumber']= result[1]
	self.config['MaxPower']= result[2]
	self.config['Chassis ID']= result[3]
	self.config['AssetTag']= result[4]
	return self.config, 200

class CartridgeCollection(Resource):

def __init__(self):
	self.rb = BASE_PATH
	self.cartridge = "Cartridge"
	self.switch = "Switch"
	self.config = {
		'@odata.context': self.rb + '$metadata#cartridgeCollection.cartridgeCollection',
		'@odata.id': self.rb + 'Cartridge',
		'@odata.type': '#cartridgeCollection.1.0.0.cartridgeCollection',
		'Name': 'Cartridge Collection',
		'Links': {}
	}
	self.config['Links']['[email protected]'] = ''
	self.config['Links']['Members'] = ''
	
def get(self,ident1,ident2):
	if ident2 == self.cartridge:
		self.config['Name']=self.cartridge + " Collection"
		self.config['Links']['[email protected]'] = 12
		self.config['Links']['Members'] = ''
		return self.config, 200
	elif ident2 == self.switch:
		self.config['Name']=self.switch + " Collection"
		self.config['Links']['[email protected]'] = 2
		self.config['Links']['Members'] = ''
		return self.config, 200

api.add_resource(ResourceCollection, '/redfish/v1')
api.add_resource(Chassis, '/redfish/v1/Chassis')
api.add_resource(Chassisinfo, '/redfish/v1/Chassis/string:ident')
api.add_resource(CartridgeCollection, '/redfish/v1/Chassis/string:ident1/string:ident2')

if name == 'main':
app.run('0.0.0.0', debug=True)

Populating should be optional

The code in emulator.py seems to assume that ./infra_gen/populate_config.json exists. The populate step should be options (come up empty if desired). Options to do this are:

  1. "POPULATE" Property is set to "emulator" in emulator_config.json
  2. Existence of ./infra_gen/populate_config.json
    # Calls INFRAGEN and populates emulator according to populate-config.json
    with open(INFRAGEN_CONFIG, 'r') as f:
        infragen_config = json.load(f)
    populate(infragen_config.get('POPULATE',10))

Restricting the creation of Composed Systems to valid previously created resources?

Hi,

I'm new to the Redfish API and maybe I'm misunderstanding the proposal of the emulator. There is a way to only allow the creation of the new system with valid resources?

From the tests I performed, the Emulator doesn't do any validation against the ResourceDictionary created when the emulator starts. It seems the initial POPULATE is used only to provide some initial examples and not to initialize which will be the valid infrastructure ...

I was expecting that in a POST to CreateGenericComputerSystem, I was enforced to provide a valid existing configuration (payload). Without this validation I was able to create systems with invalid NumberOfProcessors, for example, or any other invalid resource.

I'm misunderstanding the concept of the emulator? There is a way to do this check if a configuration is valid during the POST?

I'm trying to use it as a datacenter emulator of available resources to play (evaluate) different allocation policies of these resources, but to do that I can't have an allocation of an invalid resource. Maybe I need to create an intermediate layer to validate with the GET if the Composed system has only valid existing resources ...

Thank you!

Getting error message “AssertionError: View function mapping is overwriting an existing endpoint function

Accessing /redfish/v1/EventService produces the expected output, but causes an error message.

Running in Redfish mode
Traceback (most recent call last):
File "C:\Users\ddon\Documents\EmRf\api_emulator\redfish\EventService_api.py", line 33, in init
g.api.add_resource(SubscriptionCollectionAPI, '/redfish/v1/EventService/Subscriptions')
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask_restful_init_.py", line 404, in add_resource
self.register_view(self.app, resource, *urls, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask_restful_init
.py", line 470, in _register_view
app.add_url_rule(rule, view_func=resource_func, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask\app.py", line 64, in wrapper_func
return f(self, *args, **kwargs)
File "C:\Users\ddon\Documents\EmRf\lib\site-packages\flask\app.py", line 1051, in add_url_rule
'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: subscriptioncollectionapi

Incorrect "dummy" values in static mockup for processors

I was looking at the contents of /redfish/v1/Systems/System-/Processors/CPU in the static mockup. I think it would be helpful if the CPU data matched real processors. For example, /redfish/v1/Systems/System-7/Processors/CPU0 shows this:

"Manufacturer": "Intel(R) Corporation",
"Model": "Multi-Core Intel(R) Xeon(R) processor 7500 Series",
"ProcessorId": {
"VendorId": "GenuineIntel",
"IdentificationRegisters": "0x34AC34DC8901274A",
"EffectiveFamily": "0x42", <<< should be “0x6”
"EffectiveModel": "0x61", <<< should be “0x2E”
"Step": "0x1", <<< should be “0x6”
"MicrocodeInfo": "0x429943" <<< should be “0x0000000B” or higher

If permissible by this team, I'd be happy to make a patch with the correct values. Please let me know. Thanks!

Request to create a Python module for this tool

Currently, SNIA is extending code base to become the Swordfish Interface Emulator. The instructions for putting the packages together is getting complex. It would be simpler if ‘pip redfish-emul’ could be run, followed by ‘pip swordfish-emul’.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.