Skip to content

Commit

Permalink
Now BMCIP, Username, Password are not hardcoded anymore
Browse files Browse the repository at this point in the history
Signed-off-by: Mario Vazquez <[email protected]>
  • Loading branch information
mvazquezc committed May 13, 2022
1 parent 69c6348 commit 0033805
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 38 deletions.
43 changes: 21 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@

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:
The [app/](./app/) directory contains the FakeFish application. Inside the [custom_scripts](./app/custom_scripts/) folder we need to create the following 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|
|Script|What should it do?|Script parameters|
|------|------------------|-----------------|
|`poweron.sh`|Power on the server|`$1` BMC IP, `$2` USERNAME, `$3` PASSWORD|
|`poweroff.sh`|Power off the server|`$1` BMC IP, `$2` USERNAME, `$3` PASSWORD|
|`bootfromcdonce.sh`|Set server to boot from virtual CD once|`$1` BMC IP, `$2` USERNAME, `$3` PASSWORD|
|`mountcd.sh`|Mount the iso received in the server's virtual CD|`$1` BMC IP, `$2` USERNAME, `$3` PASSWORD, `$4` ISO FILE URL|
|`unmountcd.sh`|Unmount the iso from the server's virtual CD|`$1` BMC IP, `$2` USERNAME, `$3` PASSWORD|

The script names must match above naming, you can check the [dell_scripts](./dell_scripts/) folder to find example scripts with the correct naming.

Expand All @@ -39,32 +39,32 @@ A [Containerfile](./custom_scripts/Containerfile) is included, so users can buil

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.
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 and another one to configure which BMC IP it provides service to. On top of that, you can do a bind mount for the folder containing the scripts for managing that specific server or use the scripts inside the container image.

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
~~~sh
podman run -p 9000:9000 -e PORT=9000 -e BMC_IP=172.20.10.10 -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
~~~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
~~~sh
$ podman run -p 9000:9000 -e PORT=9000 -e BMC_IP=172.20.10.10 -v $PWD/dell_scripts:/opt/fakefish/custom_scripts:z quay.io/mavazque/fakefish:v0

* Serving Flask app 'fakefish' (lazy loading)
* Environment: production
Expand All @@ -74,11 +74,11 @@ In a successful execution you should see something like this in the logs:
* 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
~~~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 -
Expand Down Expand Up @@ -140,11 +140,11 @@ In a successful execution you should see something like this in the logs:

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
~~~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 -
Expand All @@ -167,5 +167,4 @@ In a successful execution you should see something like this in the logs:

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 -
```
~~~
41 changes: 34 additions & 7 deletions app/fakefish.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import requests
import subprocess
from datetime import datetime
from werkzeug.http import parse_authorization_header
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

Expand All @@ -18,7 +19,7 @@
except ImportError:
config = {'PORT': os.environ.get('PORT', 9000)}

debug = config['DEBUG'] if 'DEBUG' in list(config) else True
debug = bool(config['DEBUG']) if 'DEBUG' in list(config) else False
port = int(config['PORT']) if 'PORT' in list(config) else 9000

@app.route('/redfish/v1/')
Expand All @@ -35,6 +36,8 @@ def system_collection_resource():

@app.route('/redfish/v1/Systems/1', methods=['GET', 'PATCH'])
def system_resource():
username, password = get_credentials(flask.request)
global bmc_ip
if flask.request.method == 'GET':
return flask.render_template(
'fake_system.json',
Expand All @@ -54,7 +57,7 @@ def system_resource():
else:
app.logger.info('Running script that sets boot from VirtualCD once')
try:
subprocess.check_call(['custom_scripts/bootfromcdonce.sh'])
subprocess.check_call(['custom_scripts/bootfromcdonce.sh', bmc_ip, username, password])
except subprocess.CalledProcessError as e:
return ('Failed to set boot from virtualcd once', 400)

Expand All @@ -74,19 +77,21 @@ def manager_resource():
@app.route('/redfish/v1/Systems/1/Actions/ComputerSystem.Reset',
methods=['POST'])
def system_reset_action():
global bmc_ip
username, password = get_credentials(flask.request)
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'])
subprocess.check_call(['custom_scripts/poweron.sh', bmc_ip, username, password])
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'])
subprocess.check_call(['custom_scripts/poweroff.sh', bmc_ip, username, password])
except subprocess.CalledProcessError as e:
return ('Failed to poweroff the server', 400)
power_state = 'Off'
Expand All @@ -109,6 +114,8 @@ def virtualmedia_cd_resource():
@app.route('/redfish/v1/Managers/1/VirtualMedia/Cd/Actions/VirtualMedia.InsertMedia',
methods=['POST'])
def virtualmedia_insert():
global bmc_ip
username, password = get_credentials(flask.request)
image = flask.request.json.get('Image')
if not image:
return('POST only works for Image'), 400
Expand All @@ -119,36 +126,56 @@ def virtualmedia_insert():
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])
subprocess.check_call(['custom_scripts/mountcd.sh', bmc_ip, username, password, 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 bmc_ip
username, password = get_credentials(flask.request)
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'])
subprocess.check_call(['custom_scripts/unmountcd.sh', bmc_ip, username, password])
except subprocess.CalledProcessError as e:
return ('Failed to unmount virtualcd', 400)
return '', 204


def get_credentials(flask_request):
auth = flask_request.headers.get('Authorization', None)
username = ''
password = ''
if auth is not None:
creds = parse_authorization_header(auth)
username = creds.username
password = creds.password
app.logger.debug('Returning credentials')
app.logger.debug('Username: ' + username + ', password: ' + password)
return username, password

def run():
"""
"""
app.run(host='0.0.0.0', port=port, debug=False, ssl_context='adhoc')
app.run(host='0.0.0.0', port=port, debug=debug, ssl_context='adhoc')


if __name__ == '__main__':

inserted = False
image_url = ''
power_state = 'On'
bmc_ip = os.environ.get('BMC_IP', None)
if bmc_ip is not None:
app.logger.info(bmc_ip)
else:
app.logger.error('Configure the BMC IP using the environment variable BMC_IP')
exit()
run()
7 changes: 5 additions & 2 deletions dell_scripts/bootfromcdonce.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

#### IMPORTANT: This script is only meant to show how to implement required scripts to make custom hardware compatible with FakeFish. Dell hardware is supported by the `idrac-virtualmedia` provider in Metal3.
#### This script has to set the server's boot to once from cd and return 0 if operation succeeded, 1 otherwise
BMC_ENDPOINT=${1}
USERNAME=${2}
PASSWORD=${3}

/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin set iDRAC.VirtualMedia.BootOnce 1
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} set iDRAC.VirtualMedia.BootOnce 1
if [ $? -eq 0 ]; then
/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin set iDRAC.ServerBoot.FirstBootDevice VCD-DVD
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} set iDRAC.ServerBoot.FirstBootDevice VCD-DVD
if [ $? -eq 0 ]; then
exit 0
else
Expand Down
11 changes: 7 additions & 4 deletions dell_scripts/mountcd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
#### This script has to mount the iso in the server's virtualmedia and return 0 if operation succeeded, 1 otherwise
#### Note: Iso image to mount will be received as the first argument ($1)

ISO=${1}
BMC_ENDPOINT=${1}
USERNAME=${2}
PASSWORD=${3}
ISO=${4}

# Disconnect image just in case
/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin remoteimage -d
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} remoteimage -d

# Connect image
/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin remoteimage -c -l ${ISO}
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} remoteimage -c -l ${ISO}

if ! /opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin remoteimage -s | grep ${ISO}; then
if ! /opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} remoteimage -s | grep ${ISO}; then
exit 1
fi

Expand Down
5 changes: 4 additions & 1 deletion dell_scripts/poweroff.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

#### IMPORTANT: This script is only meant to show how to implement required scripts to make custom hardware compatible with FakeFish. Dell hardware is supported by the `idrac-virtualmedia` provider in Metal3.
#### This script has to poweroff the server and return 0 if operation succeeded, 1 otherwise
BMC_ENDPOINT=${1}
USERNAME=${2}
PASSWORD=${3}

/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin serveraction powerdown
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} serveraction powerdown
if [ $? -eq 0 ]; then
exit 0
else
Expand Down
5 changes: 4 additions & 1 deletion dell_scripts/poweron.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

#### IMPORTANT: This script is only meant to show how to implement required scripts to make custom hardware compatible with FakeFish. Dell hardware is supported by the `idrac-virtualmedia` provider in Metal3.
#### This script has to poweron the server and return 0 if operation succeeded, 1 otherwise
BMC_ENDPOINT=${1}
USERNAME=${2}
PASSWORD=${3}

/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin serveraction powerup
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} serveraction powerup
if [ $? -eq 0 ]; then
exit 0
else
Expand Down
5 changes: 4 additions & 1 deletion dell_scripts/unmountcd.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@

#### IMPORTANT: This script is only meant to show how to implement required scripts to make custom hardware compatible with FakeFish. Dell hardware is supported by the `idrac-virtualmedia` provider in Metal3.
#### This script has to unmount the iso from the server's virtualmedia and return 0 if operation succeeded, 1 otherwise
BMC_ENDPOINT=${1}
USERNAME=${2}
PASSWORD=${3}

# Disconnect image
/opt/dell/srvadmin/bin/idracadm7 -r 192.168.1.10 -u root -p calvin remoteimage -d
/opt/dell/srvadmin/bin/idracadm7 -r ${BMC_ENDPOINT} -u ${USERNAME} -p ${PASSWORD} remoteimage -d
if [ $? -eq 0 ]; then
exit 0
else
Expand Down

0 comments on commit 0033805

Please sign in to comment.