-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move fakefish from telco-operations repo
Signed-off-by: Mario Vazquez <[email protected]>
- Loading branch information
Showing
19 changed files
with
693 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
REGISTRY ?= quay.io | ||
IMAGE_NAMESPACE ?= mavazque | ||
IMAGE_NAME ?= fakefish | ||
IMAGE_URL ?= $(REGISTRY)/$(IMAGE_NAMESPACE)/$(IMAGE_NAME) | ||
TAG ?= latest | ||
|
||
.PHONY: build-dell build-custom pre-reqs | ||
|
||
default: pre-reqs build-custom | ||
|
||
build-dell: | ||
podman build . -f dell_scripts/Containerfile -t ${IMAGE_URL}:${TAG} | ||
|
||
build-custom: pre-reqs | ||
podman build . -f custom_scripts/Containerfile -t ${IMAGE_URL}:${TAG} | ||
|
||
.SILENT: | ||
pre-reqs: | ||
if [ $(shell find custom_scripts/ -name "*.sh" | grep -Ec "mountcd.sh|poweroff.sh|poweron.sh|unmountcd.sh|bootfromcdonce.sh") -ne 5 ];then echo 'Missing custom scripts or bad naming';exit 1;fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
# FakeFish | ||
|
||
> **WARNING**: The work exposed here is not supported in any way by Red Hat, this is the result of exploratory work. Use at your own risk. | ||
`FakeFish` is a flask based app that exposes a RedFish-like API with a set of limited endpoints that allow the deployment of OpenShift nodes via the Metal3 operator on hardware that doesn't support RedFish or doesn't follow the RedFish standard. | ||
|
||
The way it works is by running a set of scripts that interact with the hardware using vendor tools/other methods while exposing a fake RedFish API that Metal3 can query. | ||
|
||
The [app/](./app/) directory contains the FakeFish application. Inside the `app` directory we can find the [custom_scripts](./app/custom_scripts/) folder where we need to create scripts: | ||
|
||
|Script|What should it do?| | ||
|------|----------------| | ||
|`poweron.sh`|Power on the server| | ||
|`poweroff.sh`|Power off the server| | ||
|`bootfromcdonce.sh`|Set server to boot from virtual CD once| | ||
|`mountcd.sh`|Mount the iso received in the server's virtual CD| | ||
|`unmountcd.sh`|Unmount the iso from the server's virtual CD| | ||
|
||
The script names must match above naming, you can check the [dell_scripts](./dell_scripts/) folder to find example scripts with the correct naming. | ||
|
||
> **NOTE**: Dell scripts linked above are only meant to show how someone could implement the required scripts to make custom hardware compatible with FakeFish. Dell hardware is supported by the `idrac-virtualmedia` provider in Metal3. **These scripts are unsupported/unmaintained** and should be taken as a reference, nothing else. | ||
Users need to implement their own scripts, we will not maintain/add providers to this project. | ||
|
||
A [Containerfile](./custom_scripts/Containerfile) is included, so users can build their own container image out of it. | ||
|
||
## Building your own FakeFish container image | ||
|
||
1. Place your custom scripts inside the [custom_scripts](./custom_scripts/) folder. | ||
2. Run the build command: | ||
|
||
> **NOTE**: Check the Makefile vars to customize the output container image naming and tag. | ||
~~~sh | ||
make build-custom | ||
~~~ | ||
|
||
## Usage | ||
|
||
You need a FakeFish process for each server you plan to install. Think of FakeFish like if it was a custom implementation of a BMC for that specific server. | ||
|
||
Since you will be potentially running multiple FakeFish instances, you will make use of an environment variable to configure in which port a given FakeFish instance listens on. On top of that, you need to do a bind mount for the folder containing the scripts for managing that specific server. | ||
|
||
An example can be found below: | ||
|
||
> **NOTE**: Every container is mapped to a single BMC, but if more hosts are required, different ports can be used (9001, 9002,...) | ||
|
||
```sh | ||
podman run -p 9000:9000 -e PORT=9000 -v $PWD/dell_scripts:/opt/fakefish/custom_scripts:z quay.io/mavazque/fakefish:v0 | ||
sudo firewall-cmd --add-port=9000/tcp | ||
``` | ||
|
||
Then, in the `install-config.yaml` file, it is required to specify the IP where the container is running instead of the 'real' BMC: | ||
|
||
```yaml | ||
bmcAddress: redfish-virtualmedia://192.168.1.10:9000/redfish/v1/Systems/1 | ||
``` | ||
|
||
## Logs | ||
|
||
In a successful execution you should see something like this in the logs: | ||
|
||
- Starting FakeFish | ||
|
||
```sh | ||
$ podman run -p 9000:9000 -e PORT=9000 -v $PWD/dell_scripts:/opt/fakefish/custom_scripts:z quay.io/mavazque/fakefish:v0 | ||
* Serving Flask app 'fakefish' (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 | ||
* Running on all addresses. | ||
WARNING: This is a development server. Do not use it in a production deployment. | ||
* Running on https://10.19.3.25:9000/ (Press CTRL+C to quit) | ||
``` | ||
|
||
- Provisioning Logs | ||
|
||
```sh | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1/BIOS HTTP/1.1" 404 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:09] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:17:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:24] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:27] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:27] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Server is already powered OFF. | ||
10.19.3.23 - - [20/Apr/2022 13:18:32] "POST /redfish/v1/Systems/1/Actions/ComputerSystem.Reset HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Managers/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Managers/1/VirtualMedia HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Managers/1/VirtualMedia/Cd HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:33] "GET /redfish/v1/Managers/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:34] "GET /redfish/v1/Managers/1/VirtualMedia HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:34] "GET /redfish/v1/Managers/1/VirtualMedia/Cd HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Disable Remote File Started. Please check status using -s | ||
option to know Remote File Share is ENABLED or DISABLED. | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Remote Image is now Configured | ||
ShareName http://10.19.3.23:6180/redfish/boot-dc055836-d26c-4256-ba6c-222e8d4559be.iso | ||
10.19.3.23 - - [20/Apr/2022 13:18:48] "POST /redfish/v1/Managers/1/VirtualMedia/Cd/Actions/VirtualMedia.InsertMedia HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:48] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
[Key=iDRAC.Embedded.1#VirtualMedia.1] | ||
Object value modified successfully | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
[Key=iDRAC.Embedded.1#ServerBoot.1] | ||
Object value modified successfully | ||
10.19.3.23 - - [20/Apr/2022 13:18:58] "PATCH /redfish/v1/Systems/1 HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:58] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:18:58] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Server power operation successful | ||
10.19.3.23 - - [20/Apr/2022 13:19:04] "POST /redfish/v1/Systems/1/Actions/ComputerSystem.Reset HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:19:05] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
``` | ||
|
||
- Deprovisioning Logs | ||
|
||
```sh | ||
10.19.3.23 - - [20/Apr/2022 13:23:29] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:29] "GET /redfish/v1/Managers/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:29] "GET /redfish/v1/Managers/1/VirtualMedia HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:29] "GET /redfish/v1/Managers/1/VirtualMedia/Cd HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Disable Remote File Started. Please check status using -s | ||
option to know Remote File Share is ENABLED or DISABLED. | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "POST /redfish/v1/Managers/1/VirtualMedia/Cd/Actions/VirtualMedia.EjectMedia HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "GET /redfish/v1/Managers/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "GET /redfish/v1/Managers/1/VirtualMedia HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "GET /redfish/v1/Managers/1/VirtualMedia/Cd HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:55] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
10.19.3.23 - - [20/Apr/2022 13:23:56] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
Security Alert: Certificate is invalid - self signed certificate | ||
Continuing execution. Use -S option for racadm to stop execution on certificate-related errors. | ||
Server power operation successful | ||
10.19.3.23 - - [20/Apr/2022 13:24:09] "POST /redfish/v1/Systems/1/Actions/ComputerSystem.Reset HTTP/1.1" 204 - | ||
10.19.3.23 - - [20/Apr/2022 13:24:10] "GET /redfish/v1/Systems/1 HTTP/1.1" 200 - | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
#!/usr/bin/env python3 | ||
# coding=utf-8 | ||
|
||
import flask | ||
import json | ||
import os | ||
import requests | ||
import subprocess | ||
from datetime import datetime | ||
from requests.packages.urllib3.exceptions import InsecureRequestWarning | ||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning) | ||
|
||
app = flask.Flask(__name__) | ||
|
||
try: | ||
app.config.from_object('settings') | ||
config = app.config | ||
except ImportError: | ||
config = {'PORT': os.environ.get('PORT', 9000)} | ||
|
||
debug = config['DEBUG'] if 'DEBUG' in list(config) else True | ||
port = int(config['PORT']) if 'PORT' in list(config) else 9000 | ||
|
||
@app.route('/redfish/v1/') | ||
def root_resource(): | ||
return flask.render_template('root.json') | ||
|
||
@app.route('/redfish/v1/Managers') | ||
def manager_collection_resource(): | ||
return flask.render_template('managers.json') | ||
|
||
@app.route('/redfish/v1/Systems') | ||
def system_collection_resource(): | ||
return flask.render_template('systems.json') | ||
|
||
@app.route('/redfish/v1/Systems/1', methods=['GET', 'PATCH']) | ||
def system_resource(): | ||
if flask.request.method == 'GET': | ||
return flask.render_template( | ||
'fake_system.json', | ||
power_state=power_state, | ||
) | ||
else: | ||
app.logger.info('patch request') | ||
boot = flask.request.json.get('Boot') | ||
if not boot: | ||
return ('PATCH only works for Boot'), 400 | ||
if boot: | ||
target = boot.get('BootSourceOverrideTarget') | ||
mode = boot.get('BootSourceOverrideMode') | ||
if not target and not mode: | ||
return ('Missing the BootSourceOverrideTarget and/or ' | ||
'BootSourceOverrideMode element', 400) | ||
else: | ||
app.logger.info('Running script that sets boot from VirtualCD once') | ||
try: | ||
subprocess.check_call(['custom_scripts/bootfromcdonce.sh']) | ||
except subprocess.CalledProcessError as e: | ||
return ('Failed to set boot from virtualcd once', 400) | ||
|
||
return '', 204 | ||
|
||
@app.route('/redfish/v1/Systems/1/EthernetInterfaces', methods=['GET']) | ||
def manage_interfaces(): | ||
return flask.render_template('fake_interfaces.json') | ||
|
||
@app.route('/redfish/v1/Managers/1', methods=['GET']) | ||
def manager_resource(): | ||
return flask.render_template( | ||
'fake_manager.json', | ||
date_time=datetime.now().strftime('%Y-%M-%dT%H:%M:%S+00:00'), | ||
) | ||
|
||
@app.route('/redfish/v1/Systems/1/Actions/ComputerSystem.Reset', | ||
methods=['POST']) | ||
def system_reset_action(): | ||
reset_type = flask.request.json.get('ResetType') | ||
global power_state | ||
if reset_type == 'On': | ||
app.logger.info('Running script that powers on the server') | ||
try: | ||
subprocess.check_call(['custom_scripts/poweron.sh']) | ||
except subprocess.CalledProcessError as e: | ||
return ('Failed to poweron the server', 400) | ||
power_state = 'On' | ||
else: | ||
app.logger.info('Running script that powers off the server') | ||
try: | ||
subprocess.check_call(['custom_scripts/poweroff.sh']) | ||
except subprocess.CalledProcessError as e: | ||
return ('Failed to poweroff the server', 400) | ||
power_state = 'Off' | ||
|
||
return '', 204 | ||
|
||
|
||
@app.route('/redfish/v1/Managers/1/VirtualMedia', methods=['GET']) | ||
def virtualmedia_collection_resource(): | ||
return flask.render_template('virtualmedias.json') | ||
|
||
@app.route('/redfish/v1/Managers/1/VirtualMedia/Cd', methods=['GET']) | ||
def virtualmedia_cd_resource(): | ||
return flask.render_template( | ||
'virtualmedia_cd.json', | ||
inserted=inserted, | ||
image_url=image_url, | ||
) | ||
|
||
@app.route('/redfish/v1/Managers/1/VirtualMedia/Cd/Actions/VirtualMedia.InsertMedia', | ||
methods=['POST']) | ||
def virtualmedia_insert(): | ||
image = flask.request.json.get('Image') | ||
if not image: | ||
return('POST only works for Image'), 400 | ||
else: | ||
global inserted | ||
global image_url | ||
inserted = True | ||
image_url = image | ||
app.logger.info('Running script that mounts cd with iso %s', image) | ||
try: | ||
subprocess.check_call(['custom_scripts/mountcd.sh', image_url]) | ||
except subprocess.CalledProcessError as e: | ||
return ('Failed to mount virtualcd', 400) | ||
return '', 204 | ||
|
||
@app.route('/redfish/v1/Managers/1/VirtualMedia/Cd/Actions/VirtualMedia.EjectMedia', | ||
methods=['POST']) | ||
def virtualmedia_eject(): | ||
global inserted | ||
global image_url | ||
inserted = False | ||
image_url = '' | ||
app.logger.info('Running script that unmounts cd') | ||
try: | ||
subprocess.check_call(['custom_scripts/unmountcd.sh']) | ||
except subprocess.CalledProcessError as e: | ||
return ('Failed to unmount virtualcd', 400) | ||
return '', 204 | ||
|
||
|
||
def run(): | ||
""" | ||
""" | ||
app.run(host='0.0.0.0', port=port, debug=False, ssl_context='adhoc') | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
inserted = False | ||
image_url = '' | ||
power_state = 'On' | ||
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"@odata.type": "#EthernetInterfaceCollection.EthernetInterfaceCollection", | ||
"Name": "Ethernet Interface Collection", | ||
"Description": "Fake NICs", | ||
"[email protected]": 0, | ||
"Members": [ | ||
|
||
], | ||
"Oem": {}, | ||
"@odata.context": "/redfish/v1/$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection", | ||
"@odata.id": "/redfish/v1/Systems/1" | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"@Redfish.Copyright": "Copyright 2014-2017 Distributed Management Task Force, Inc. (DMTF). For the full DMTF copyright policy, see http://www.dmtf.org/about/policies/copyright.", | ||
"@odata.context": "/redfish/v1/$metadata#Manager.Manager", | ||
"@odata.id": "/redfish/v1/Managers/1", | ||
"@odata.type": "#Manager.v1_3_1.Manager", | ||
"DateTime": {{ date_time|string|tojson }}, | ||
"DateTimeLocalOffset": "+00:00", | ||
"Description": "FakeFish BMC", | ||
"FirmwareVersion": "1.00", | ||
"Id": "1", | ||
"Links": { | ||
"ManagerForChassis": [ | ||
{ | ||
"@odata.id": "/redfish/v1/Chassis/fake-chassis" | ||
} | ||
], | ||
"ManagerForServers": [ | ||
{ | ||
"@odata.id": "/redfish/v1/Systems/1" | ||
} | ||
] | ||
}, | ||
"ManagerType": "BMC", | ||
"Model": "Palc 2000", | ||
"Name": "FakeFish Manager", | ||
"PowerState": "On", | ||
"ServiceEntryPointUUID": null, | ||
"Status": { | ||
"Health": "OK", | ||
"State": "Enabled" | ||
}, | ||
"UUID": "1", | ||
"VirtualMedia": { | ||
"@odata.id": "/redfish/v1/Managers/1/VirtualMedia" | ||
} | ||
} | ||
|
Oops, something went wrong.